@teispace/next-maker 1.11.0 → 1.12.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 (134) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +196 -272
  3. package/dist/index.js +341 -223
  4. package/dist/index.js.map +4 -4
  5. package/dist/src/commands/component.d.ts +3 -0
  6. package/dist/src/commands/component.d.ts.map +1 -0
  7. package/dist/src/commands/feature.d.ts.map +1 -1
  8. package/dist/src/commands/hook.d.ts +3 -0
  9. package/dist/src/commands/hook.d.ts.map +1 -0
  10. package/dist/src/commands/index.d.ts.map +1 -1
  11. package/dist/src/commands/locale.d.ts +3 -0
  12. package/dist/src/commands/locale.d.ts.map +1 -0
  13. package/dist/src/commands/page.d.ts +3 -0
  14. package/dist/src/commands/page.d.ts.map +1 -0
  15. package/dist/src/commands/service.d.ts.map +1 -1
  16. package/dist/src/commands/slice.d.ts.map +1 -1
  17. package/dist/src/config/paths.d.ts +4 -0
  18. package/dist/src/config/paths.d.ts.map +1 -1
  19. package/dist/src/detection/existence.checker.d.ts +9 -0
  20. package/dist/src/detection/existence.checker.d.ts.map +1 -0
  21. package/dist/src/detection/index.d.ts +4 -0
  22. package/dist/src/detection/index.d.ts.map +1 -0
  23. package/dist/src/{services/feature/detection.service.d.ts → detection/project.detector.d.ts} +1 -2
  24. package/dist/src/detection/project.detector.d.ts.map +1 -0
  25. package/dist/src/generators/component.generator.d.ts +9 -0
  26. package/dist/src/generators/component.generator.d.ts.map +1 -0
  27. package/dist/src/generators/crud-service.generator.d.ts +6 -0
  28. package/dist/src/generators/crud-service.generator.d.ts.map +1 -0
  29. package/dist/src/generators/feature.generator.d.ts +7 -0
  30. package/dist/src/generators/feature.generator.d.ts.map +1 -0
  31. package/dist/src/generators/hook.generator.d.ts +8 -0
  32. package/dist/src/generators/hook.generator.d.ts.map +1 -0
  33. package/dist/src/generators/index.d.ts +14 -0
  34. package/dist/src/generators/index.d.ts.map +1 -0
  35. package/dist/src/generators/locale.generator.d.ts +10 -0
  36. package/dist/src/generators/locale.generator.d.ts.map +1 -0
  37. package/dist/src/generators/page.generator.d.ts +10 -0
  38. package/dist/src/generators/page.generator.d.ts.map +1 -0
  39. package/dist/src/generators/service.generator.d.ts +6 -0
  40. package/dist/src/generators/service.generator.d.ts.map +1 -0
  41. package/dist/src/generators/slice.generator.d.ts +11 -0
  42. package/dist/src/generators/slice.generator.d.ts.map +1 -0
  43. package/dist/src/generators/templates/barrel.template.d.ts +12 -0
  44. package/dist/src/generators/templates/barrel.template.d.ts.map +1 -0
  45. package/dist/src/generators/templates/component.template.d.ts +5 -0
  46. package/dist/src/generators/templates/component.template.d.ts.map +1 -0
  47. package/dist/src/generators/templates/crud-service.template.d.ts +10 -0
  48. package/dist/src/generators/templates/crud-service.template.d.ts.map +1 -0
  49. package/dist/src/generators/templates/custom-hook.template.d.ts +5 -0
  50. package/dist/src/generators/templates/custom-hook.template.d.ts.map +1 -0
  51. package/dist/src/generators/templates/hook.template.d.ts +9 -0
  52. package/dist/src/generators/templates/hook.template.d.ts.map +1 -0
  53. package/dist/src/generators/templates/page.template.d.ts +18 -0
  54. package/dist/src/generators/templates/page.template.d.ts.map +1 -0
  55. package/dist/src/generators/templates/persist.template.d.ts +6 -0
  56. package/dist/src/generators/templates/persist.template.d.ts.map +1 -0
  57. package/dist/src/generators/templates/selectors.template.d.ts +6 -0
  58. package/dist/src/generators/templates/selectors.template.d.ts.map +1 -0
  59. package/dist/src/generators/templates/service.template.d.ts +5 -0
  60. package/dist/src/generators/templates/service.template.d.ts.map +1 -0
  61. package/dist/src/generators/templates/shared-component.template.d.ts +10 -0
  62. package/dist/src/generators/templates/shared-component.template.d.ts.map +1 -0
  63. package/dist/src/generators/templates/slice.template.d.ts +6 -0
  64. package/dist/src/generators/templates/slice.template.d.ts.map +1 -0
  65. package/dist/src/generators/templates/types.template.d.ts +5 -0
  66. package/dist/src/generators/templates/types.template.d.ts.map +1 -0
  67. package/dist/src/generators/types.d.ts +19 -0
  68. package/dist/src/generators/types.d.ts.map +1 -0
  69. package/dist/src/modifiers/api-registration.modifier.d.ts +6 -0
  70. package/dist/src/modifiers/api-registration.modifier.d.ts.map +1 -0
  71. package/dist/src/modifiers/app-paths.modifier.d.ts +5 -0
  72. package/dist/src/modifiers/app-paths.modifier.d.ts.map +1 -0
  73. package/dist/src/modifiers/crud-api-registration.modifier.d.ts +5 -0
  74. package/dist/src/modifiers/crud-api-registration.modifier.d.ts.map +1 -0
  75. package/dist/src/modifiers/helpers.d.ts +14 -0
  76. package/dist/src/modifiers/helpers.d.ts.map +1 -0
  77. package/dist/src/modifiers/index.d.ts +7 -0
  78. package/dist/src/modifiers/index.d.ts.map +1 -0
  79. package/dist/src/modifiers/root-reducer.modifier.d.ts +7 -0
  80. package/dist/src/modifiers/root-reducer.modifier.d.ts.map +1 -0
  81. package/dist/src/modifiers/translation.modifier.d.ts +5 -0
  82. package/dist/src/modifiers/translation.modifier.d.ts.map +1 -0
  83. package/dist/src/modifiers/types.d.ts +15 -0
  84. package/dist/src/modifiers/types.d.ts.map +1 -0
  85. package/dist/src/pipelines/feature.pipeline.d.ts +14 -0
  86. package/dist/src/pipelines/feature.pipeline.d.ts.map +1 -0
  87. package/dist/src/pipelines/index.d.ts +9 -0
  88. package/dist/src/pipelines/index.d.ts.map +1 -0
  89. package/dist/src/pipelines/runner.d.ts +7 -0
  90. package/dist/src/pipelines/runner.d.ts.map +1 -0
  91. package/dist/src/pipelines/service.pipeline.d.ts +8 -0
  92. package/dist/src/pipelines/service.pipeline.d.ts.map +1 -0
  93. package/dist/src/pipelines/slice.pipeline.d.ts +9 -0
  94. package/dist/src/pipelines/slice.pipeline.d.ts.map +1 -0
  95. package/dist/src/pipelines/types.d.ts +12 -0
  96. package/dist/src/pipelines/types.d.ts.map +1 -0
  97. package/dist/src/prompts/component.prompt.d.ts +6 -0
  98. package/dist/src/prompts/component.prompt.d.ts.map +1 -0
  99. package/dist/src/prompts/hook.prompt.d.ts +5 -0
  100. package/dist/src/prompts/hook.prompt.d.ts.map +1 -0
  101. package/dist/src/prompts/locale.prompt.d.ts +9 -0
  102. package/dist/src/prompts/locale.prompt.d.ts.map +1 -0
  103. package/dist/src/prompts/page.prompt.d.ts +7 -0
  104. package/dist/src/prompts/page.prompt.d.ts.map +1 -0
  105. package/dist/src/services/init/cleanup/dark-mode.cleanup.d.ts +3 -0
  106. package/dist/src/services/init/cleanup/dark-mode.cleanup.d.ts.map +1 -0
  107. package/dist/src/services/init/cleanup/http.cleanup.d.ts +3 -0
  108. package/dist/src/services/init/cleanup/http.cleanup.d.ts.map +1 -0
  109. package/dist/src/services/init/cleanup/i18n.cleanup.d.ts +3 -0
  110. package/dist/src/services/init/cleanup/i18n.cleanup.d.ts.map +1 -0
  111. package/dist/src/services/init/cleanup/index.d.ts +3 -0
  112. package/dist/src/services/init/cleanup/index.d.ts.map +1 -0
  113. package/dist/src/services/init/cleanup/misc.cleanup.d.ts +13 -0
  114. package/dist/src/services/init/cleanup/misc.cleanup.d.ts.map +1 -0
  115. package/dist/src/services/init/cleanup/redux.cleanup.d.ts +3 -0
  116. package/dist/src/services/init/cleanup/redux.cleanup.d.ts.map +1 -0
  117. package/package.json +9 -7
  118. package/dist/src/services/common/api-registration.service.d.ts +0 -7
  119. package/dist/src/services/common/api-registration.service.d.ts.map +0 -1
  120. package/dist/src/services/feature/detection.service.d.ts.map +0 -1
  121. package/dist/src/services/feature/registration.service.d.ts +0 -6
  122. package/dist/src/services/feature/registration.service.d.ts.map +0 -1
  123. package/dist/src/services/feature/templates.service.d.ts +0 -11
  124. package/dist/src/services/feature/templates.service.d.ts.map +0 -1
  125. package/dist/src/services/init/cleanup.service.d.ts +0 -3
  126. package/dist/src/services/init/cleanup.service.d.ts.map +0 -1
  127. package/dist/src/services/service/detection.service.d.ts +0 -2
  128. package/dist/src/services/service/detection.service.d.ts.map +0 -1
  129. package/dist/src/services/service/service.service.d.ts +0 -8
  130. package/dist/src/services/service/service.service.d.ts.map +0 -1
  131. package/dist/src/services/slice/detection.service.d.ts +0 -2
  132. package/dist/src/services/slice/detection.service.d.ts.map +0 -1
  133. package/dist/src/services/slice/slice.service.d.ts +0 -7
  134. package/dist/src/services/slice/slice.service.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,41 +1,41 @@
1
1
  #!/usr/bin/env node
2
- var ai=Object.defineProperty;var Ce=(e,t)=>()=>(e&&(t=e(e=0)),t);var Xe=(e,t)=>{for(var i in t)ai(e,i,{get:t[i],enumerable:!0})};import Z from"node:fs/promises";import We from"node:path";import{existsSync as Te}from"node:fs";var d,u,b,C,S,ne,l,T=Ce(()=>{"use strict";d=async e=>Z.readFile(e,"utf-8"),u=async(e,t)=>{await Z.mkdir(We.dirname(e),{recursive:!0}),await Z.writeFile(e,t,"utf-8")},b=async(e,t)=>{await Z.mkdir(We.dirname(t),{recursive:!0}),await Z.copyFile(e,t)},C=async e=>{Te(e)&&await Z.unlink(e)},S=async e=>{Te(e)&&await Z.rm(e,{recursive:!0,force:!0})},ne=async(e,t)=>{let i=await d(e),r=JSON.parse(i),s=t(r);await u(e,JSON.stringify(s,null,2))},l=e=>Te(e)});var Ze={};Xe(Ze,{PROJECT_PATHS:()=>a});var a,N=Ce(()=>{"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"}});var et={};Xe(et,{cleanupHttpTypes:()=>oe,isFileUsed:()=>Ri,isStringUsed:()=>Ni,migrateClientUsages:()=>$e,removeHttpExports:()=>_e,updateConfigIndex:()=>Oe,updateHttpIndex:()=>Re,updateTypesIndex:()=>Ae,updateUtilsIndex:()=>Ne});import A from"node:path";import{exec as Ei}from"node:child_process";import{promisify as Ii}from"node:util";var Ie,Re,Ne,Ae,Oe,oe,$e,_e,Ri,Ni,fe=Ce(()=>{"use strict";T();N();Ie=Ii(Ei),Re=async(e,t)=>{let i=A.join(e,a.HTTP_UTILS,"index.ts");if(l(i)){let r=await d(i);r=r.replace(/export .* from '\.\/axios-client';?\n?/g,""),r=r.replace(/export .* from '\.\/fetch-client';?\n?/g,""),t.includes("fetch")&&!r.includes("fetch-client")&&(r+=`export * from './fetch-client';
3
- `),t.includes("axios")&&!r.includes("axios-client")&&(r+=`export * from './axios-client';
4
- `),await u(i,r)}},Ne=async e=>{let t=A.join(e,a.UTILS_INDEX);if(l(t)){let i=await d(t);i.includes("./http")||(i+=`export * from './http';
5
- `,await u(t,i))}},Ae=async e=>{let t=A.join(e,a.TYPES_INDEX);if(l(t)){let i=await d(t);i.includes("./common")||(i+=`export * from './common';
6
- `),i.includes("./utility")||(i+=`export * from './utility';
7
- `),await u(t,i)}},Oe=async e=>{let t=A.join(e,a.CONFIG_INDEX);if(l(t)){let i=await d(t);i.includes("./app-apis")||(i+=`export * from './app-apis';
8
- `,await u(t,i))}},oe=async(e,t)=>{let i=A.join(e,a.HTTP_TYPES);if(l(i)){let r=await d(i);t.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,`
2
+ var wr=Object.defineProperty;var se=(e,o)=>()=>(e&&(o=e(e=0)),o);var Me=(e,o)=>{for(var t in o)wr(e,t,{get:o[t],enumerable:!0})};import te from"node:fs/promises";import It from"node:path";import{existsSync as Ue}from"node:fs";var d,u,O,P,h,me,l,w=se(()=>{"use strict";d=async e=>te.readFile(e,"utf-8"),u=async(e,o)=>{await te.mkdir(It.dirname(e),{recursive:!0}),await te.writeFile(e,o,"utf-8")},O=async(e,o)=>{await te.mkdir(It.dirname(o),{recursive:!0}),await te.copyFile(e,o)},P=async e=>{Ue(e)&&await te.unlink(e)},h=async e=>{Ue(e)&&await te.rm(e,{recursive:!0,force:!0})},me=async(e,o)=>{let t=await d(e),r=JSON.parse(t),n=o(r);await u(e,JSON.stringify(n,null,2))},l=e=>Ue(e)});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";w();T();Je=Hr(Lr),Ye=async(e,o)=>{let t=R.join(e,a.HTTP_UTILS,"index.ts");if(l(t)){let r=await d(t);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(t,r)}},ze=async e=>{let o=R.join(e,a.UTILS_INDEX);if(l(o)){let t=await d(o);t.includes("./http")||(t+=`export * from './http';
5
+ `,await u(o,t))}},We=async e=>{let o=R.join(e,a.TYPES_INDEX);if(l(o)){let t=await d(o);t.includes("./common")||(t+=`export * from './common';
6
+ `),t.includes("./utility")||(t+=`export * from './utility';
7
+ `),await u(o,t)}},Be=async e=>{let o=R.join(e,a.CONFIG_INDEX);if(l(o)){let t=await d(o);t.includes("./app-apis")||(t+=`export * from './app-apis';
8
+ `,await u(o,t))}},ae=async(e,o)=>{let t=R.join(e,a.HTTP_TYPES);if(l(t)){let r=await d(t);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
9
 
10
10
  `).trim()+`
11
- `,await u(i,r))}},$e=async(e,t,i)=>{if(t===i)return;let r=t==="fetch"?"fetchClient":"axiosClient",s=i==="fetch"?"fetchClient":"axiosClient",o=t==="fetch"?"fetch-client":"axios-client",n=i==="fetch"?"fetch-client":"axios-client",c=A.join(e,"src");try{let p=`grep -rl "${r}" "${c}" --include="*.ts" --include="*.tsx" || true`,{stdout:m}=await Ie(p);if(!m.trim())return;let h=m.trim().split(`
12
- `).filter(y=>y);for(let y of h){if(!l(y))continue;let x=await d(y),w=!1,D=new RegExp(`(import\\s*\\{[^}]*?)\\b${r}\\b([^}]*?\\}\\s*from\\s*['"][^'"]*?/http['"])`,"g");D.test(x)&&(x=x.replace(D,`$1${s}$2`),w=!0);let I=new RegExp(`import\\s+${r}\\s+from\\s+['"]([^'"]*?)/${o}['"]`,"g");I.test(x)&&(x=x.replace(I,`import ${s} from '$1/${n}'`),w=!0);let F=new RegExp(`\\b${r}\\b(?=\\.)`,"g");F.test(x)&&(x=x.replace(F,s),w=!0);let ie=new RegExp(`\\b${r}\\b(?![.\\w])`,"g");ie.test(x)&&(x=x.replace(ie,s),w=!0),w&&await u(y,x)}}catch(p){console.warn("Warning: Could not scan for HTTP client usages:",p)}},_e=async e=>{let t=A.join(e,a.UTILS_INDEX);if(l(t)){let r=await d(t);r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http['"];?.*$/gm,""),await u(t,r)}let i=A.join(e,a.TYPES_INDEX);if(l(i)){let r=await d(i),s=A.join(e,a.COMMON_TYPES_DIR);if(!l(s))r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/common['"];?.*$/gm,"");else{let o=A.join(s,"index.ts");if(l(o)){let n=await d(o);n=n.replace(/^\s*export\s+\*\s+from\s+['"]\.\/http\.types['"];?.*$/gm,""),await u(o,n)}}l(A.join(e,a.UTILITY_TYPES_DIR))||(r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/utility['"];?.*$/gm,"")),await u(i,r)}},Ri=async(e,t,i=[])=>{let r=A.join(e,"src"),o=`grep -r "from ['\\"].*${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}.*['\\"]" "${r}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:n}=await Ie(o);return n.trim()?n.trim().split(`
13
- `).filter(m=>{let[h]=m.split(":"),y=A.resolve(e,h);return!i.some(x=>!!(y===x||y.startsWith(x+A.sep)))}).length>0:!1}catch(n){return console.warn(`Warning: Failed to check usage for ${t}:`,n),!0}},Ni=async(e,t,i=[])=>{let r=A.join(e,"src"),o=`grep -r "${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}" "${r}" --include="*.ts" --include="*.tsx" || true`;try{let{stdout:n}=await Ie(o);return n.trim()?n.trim().split(`
14
- `).filter(m=>{let[h]=m.split(":"),y=A.resolve(e,h);return!i.some(x=>!!(y===x||y.startsWith(x+A.sep)))}).length>0:!1}catch(n){return console.warn(`Warning: Failed to check usage for string ${t}:`,n),!0}}});import{Command as Mo}from"commander";import Fe from"node:path";import K from"picocolors";import ci from"ora";function $(e="",t){let i=ci({text:e,...t});return i.start(),i}import li from"enquirer";var{prompt:pi}=li,Je=async e=>{let t=await pi([{type:"input",name:"projectName",message:"What is the project name?",initial:e||"my-app",skip:!!e,validate:i=>/^[a-z0-9-_]+$/.test(i)?!0:"Project name must be lowercase and contain only alphanumeric characters, hyphens, and underscores."},{type:"input",name:"description",message:"Project description:",initial:"A Next.js application"},{type:"input",name:"author",message:"Author:",initial:"Teispace"},{type:"input",name:"version",message:"Version:",initial:"0.1.0",validate:i=>/^\d+\.\d+\.\d+$/.test(i)?!0:"Version must be a valid semantic version (x.y.z)."},{type:"input",name:"email",message:"Support email:",initial:"support@example.com",validate:i=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(i)?!0:"Please enter a valid email address."},{type:"select",name:"packageManager",message:"Which package manager would you like to use?",choices:["npm","yarn","pnpm","bun"],initial:1},{type:"input",name:"gitRemote",message:"GitHub repository URL (optional):",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:i=>i?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+\/issues$/.test(i)?!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:i=>i?/^https:\/\/github\.com\/[\w-]+\/[\w.-]+#readme$/.test(i)?!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 i=this.state?.answers??this.enquirer?.answers??{};return!!(i.httpClient&&i.httpClient!=="none")}},{type:"confirm",name:"darkMode",message:"Do you want to include Dark Mode (Tailwind + next-themes)?",initial:!0},{type:"confirm",name:"redux",message:"Do you want to include Redux Toolkit?",initial:!0},{type:"confirm",name:"i18n",message:"Do you want to include Internationalization (next-intl)?",initial:!0},{type:"multiselect",name:"communityFiles",message:"Select community files to include:",choices:[{name:"CODE_OF_CONDUCT.md",value:"CODE_OF_CONDUCT.md"},{name:"CONTRIBUTING.md",value:"CONTRIBUTING.md"},{name:"SECURITY.md",value:"SECURITY.md"}],initial:[]},{type:"confirm",name:"readme",message:"Do you want to create a README.md?",initial:!0},{type:"confirm",name:"docker",message:"Do you want to include Docker configuration?",initial:!1},{type:"input",name:"containerName",message:"Docker Container Name:",initial:"next-app",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(i)?!0:"Invalid Docker container name."},{type:"input",name:"imageName",message:"Docker Image Name:",initial:"nextjs-starter",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/.test(i)?!0:"Invalid Docker image name (must be lowercase)."},{type:"input",name:"imageTag",message:"Docker Image Tag:",initial:"latest",skip:function(){return!(this.state?.answers??this.enquirer?.answers??{}).docker},validate:i=>/^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$/.test(i)?!0:"Invalid Docker image tag."},{type:"confirm",name:"ci",message:"Do you want to include GitHub Actions (CI/CD)?",initial:!1},{type:"confirm",name:"preCommitHooks",message:"Do you want to setup pre-commit hooks (Husky, Commitlint, Lint-staged)?",initial:!0},{type:"confirm",name:"commitizen",message:"Do you want to setup Commitizen?",initial:!0},{type:"confirm",name:"copyEnv",message:"Want to copy .env.example to .env?",initial:!0}]);if(t.company=t.author,t.gitRemote&&!t.gitHomepage){let i=t.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");t.gitHomepage=`${i}#readme`,t.gitIssues=`${i}/issues`}return t};T();import{exec as mi}from"node:child_process";import{promisify as di}from"node:util";var Y=di(mi),ze=async(e,t,i)=>{try{if(await Y("git init",{cwd:e}),await Y("git add .",{cwd:e}),await Y('git commit -m "Initial commit from @teispace/next-maker"',{cwd:e}),t&&(await Y(`git remote add origin ${t}`,{cwd:e}),i)){await Y("git fetch origin",{cwd:e});let r="main";try{await Y("git show-branch origin/main",{cwd:e})}catch{try{await Y("git show-branch origin/master",{cwd:e}),r="master"}catch{r="main"}}await Y(`git merge origin/${r} --allow-unrelated-histories -X ours`,{cwd:e}),await Y(`git push origin HEAD:${r}`,{cwd:e})}}catch(r){console.warn("Failed to initialize git repository",r)}};import{exec as ui}from"node:child_process";import{promisify as fi}from"node:util";var de=fi(ui),Ve=async(e,t)=>{let i=`${t} install`;try{await de(i,{cwd:e})}catch(r){throw new Error(`Failed to install dependencies with ${t}: ${r}`)}},H=async(e,t,i)=>{let r=t==="npm"?`${t} run ${i}`:`${t} ${i}`;try{await de(r,{cwd:e})}catch(s){console.warn(`Warning: Failed to run script '${i}': ${s}`)}},gi=()=>{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"},G=async e=>{let{existsSync:t}=await import("node:fs"),i=await import("node:path");return t(i.join(e,"pnpm-lock.yaml"))?"pnpm":t(i.join(e,"yarn.lock"))?"yarn":t(i.join(e,"bun.lockb"))?"bun":t(i.join(e,"package-lock.json"))?"npm":gi()},xi=async(e,t,i)=>{if(i.length===0)return;let s=`${hi(t)} ${i.join(" ")}`;try{await de(s,{cwd:e})}catch(o){throw new Error(`Failed to install packages with ${t}: ${o}`)}},hi=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"}},M=async(e,t)=>{let i=await G(e);await xi(e,i,[t])},yi=async(e,t,i)=>{if(i.length===0)return;let s=`${Si(t)} ${i.join(" ")}`;try{await de(s,{cwd:e})}catch(o){throw new Error(`Failed to uninstall packages with ${t}: ${o}`)}},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"}},Ee=async(e,t)=>{let i=await G(e);await yi(e,i,[t])};import U from"picocolors";var Pi={reset:e=>e,red:U.red,green:U.green,yellow:U.yellow,blue:U.blue,cyan:U.cyan,magenta:U.magenta,white:U.white,gray:U.gray,bright:U.bold,dim:U.dim};function Q(e,t="reset"){let i=Pi[t]??(r=>r);console.log(i(e))}function ue(e){Q(`\u2716 ${e}`,"red")}var R=ue;function f(e){Q(e)}function Ke(){console.log(""),Q("\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"),Q("\u2551 \u2551","cyan"),Q("\u2551 \u{1F680} Create Teispace Next.js App \u{1F680} \u2551","cyan"),Q("\u2551 \u2551","cyan"),Q("\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 Be(e){let{logger:t=n=>console.error(n),exitOnCancel:i=process.env.NODE_ENV!=="test"}=e??{},r=()=>{console.log(""),console.log(""),t("Setup cancelled by user"),console.log(""),i&&process.exit(0)},s=n=>{if(n!==null&&typeof n=="object"&&"code"in n&&n.code==="ERR_USE_AFTER_CLOSE"){r();return}if(n instanceof Error){t(`Uncaught exception: ${n.message}`);return}t(`Uncaught exception: ${String(n)}`)},o=n=>{if(n instanceof Error){t(`Unhandled promise rejection: ${n.message}`);return}t(`Unhandled promise rejection: ${String(n)}`)};return process.on("SIGINT",r),process.on("SIGTERM",r),process.on("uncaughtException",s),process.on("unhandledRejection",o),()=>{process.off("SIGINT",r),process.off("SIGTERM",r),process.off("uncaughtException",s),process.off("unhandledRejection",o)}}var vi=e=>e.charAt(0).toUpperCase()+e.slice(1),L=e=>e.replace(/-([a-z])/g,(t,i)=>i.toUpperCase()),V=e=>vi(L(e));import wi from"ora";var v=wi();import Ci from"degit";var qe=async e=>{let t=$("Downloading template...");try{await Ci("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(e),t.succeed("Template downloaded successfully.")}catch(i){throw t.fail("Failed to download template."),i}};T();import Ti from"node:path";N();var _={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 Qe=async(e,t)=>{let i=$("Configuring package.json...");try{let r=t.gitRemote,s=t.gitHomepage,o=t.gitIssues;t.gitRemote&&(t.gitRemote.startsWith("git@github.com:")&&(r=t.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"")),s||(s=`${r.replace(/\.git$/,"")}#readme`),o||(o=`${r.replace(/\.git$/,"")}/issues`),r.endsWith(".git")||(r=`${r}.git`)),await ne(Ti.join(e,a.PACKAGE_JSON),n=>(n.name=t.projectName,n.version=t.version,n.description=t.description,n.author=t.author,delete n.packageManager,t.gitRemote?(s&&(n.homepage=s),o&&(n.bugs={url:o}),r&&(n.repository={type:"git",url:r})):(delete n.homepage,delete n.bugs,delete n.repository),t.redux||(delete n.dependencies[_.REDUX_TOOLKIT],delete n.dependencies[_.REACT_REDUX],delete n.dependencies[_.REDUX_PERSIST]),t.httpClient!=="none"||t.reactSecureStorage||delete n.dependencies[_.REACT_SECURE_STORAGE],t.i18n||delete n.dependencies[_.NEXT_INTL],t.darkMode||delete n.dependencies[_.NEXT_THEMES],t.httpClient==="none"?delete n.dependencies[_.AXIOS]:t.httpClient==="fetch"&&delete n.dependencies[_.AXIOS],n)),i.succeed("package.json configured.")}catch(r){throw i.fail("Failed to configure package.json."),r}};T();import g from"node:path";N();fe();var tt=async(e,t)=>{let i=$("Customizing features...");try{await Ai(e,t),await Oi(e,t),await $i(e,t),await _i(e,t),await bi(e,t),await Fi(e),await ji(e),await ki(e),i.succeed("Features customized.")}catch(r){throw i.fail("Failed to customize features."),r}},Ai=async(e,t)=>{let i=g.join(e,a.HTTP_UTILS),r=t.httpClient!=="none"||t.reactSecureStorage;if(t.httpClient==="none"){if(await S(g.join(e,a.AXIOS_CLIENT)),await S(g.join(e,a.FETCH_CLIENT)),r)await u(g.join(i,"index.ts"),`export * from './token-store';
15
- `),await C(g.join(e,a.CLIENT_UTILS)),await oe(e,[]);else{await S(i);let o=g.join(e,a.UTILS_INDEX);if(l(o)){let c=await d(o);c=c.replace(/export \* from '\.\/http';\n/,""),await u(o,c)}await C(g.join(e,a.APP_APIS));let n=g.join(e,a.CONFIG_INDEX);if(l(n)){let c=await d(n);c=c.replace(/export \* from '\.\/app-apis';\n/,""),await u(n,c)}}let s=g.join(e,a.CONSTANTS);if(l(s)){let o=await d(s);o=o.replace(/export const API_RESPONSE_DATA_KEY = 'data';\n/,""),o=o.replace(/export const SAVE_AUTH_TOKENS = false;\n/,""),await u(s,o)}if(await S(g.join(e,a.ERRORS_DIR)),!r){await S(g.join(e,a.COMMON_TYPES_DIR)),await S(g.join(e,a.UTILITY_TYPES_DIR));let o=g.join(e,a.TYPES_INDEX);if(l(o)){let n=await d(o);n=n.replace(/export \* from '\.\/utility';\n/,""),n=n.replace(/export \* from '\.\/common';\n/,""),await u(o,n)}}}else if(t.httpClient==="axios"){await S(g.join(e,a.FETCH_CLIENT));let s=await d(g.join(i,"index.ts"));s=s.replace(/export .* from '\.\/fetch-client';\n/g,""),await u(g.join(i,"index.ts"),s);let o=g.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)}}else if(t.httpClient==="fetch"){await S(g.join(e,a.AXIOS_CLIENT));let s=await d(g.join(i,"index.ts"));s=s.replace(/export .* from '\.\/axios-client';\n/g,""),await u(g.join(i,"index.ts"),s),await oe(e,["fetch"]);let o=g.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)}}},Oi=async(e,t)=>{t.httpClient!=="none"||t.reactSecureStorage||await S(g.join(e,a.STORAGE_SERVICE))},$i=async(e,t)=>{if(!t.redux){await S(g.join(e,a.STORE)),await S(g.join(e,a.COUNTER_FEATURE)),await C(g.join(e,a.STORE_PROVIDER));let i=g.join(e,a.PROVIDERS_INDEX),r=await d(i);r=r.replace(/export \* from '\.\/StoreProvider';\n/,""),await u(i,r);let s=[g.join(e,a.ROOT_PAGE),g.join(e,a.LOCALE_PAGE)];for(let o of s)if(l(o)){let n=await d(o);n=n.replace(/import\s+\{\s*Counter\s*\}\s+from\s+['"]@\/features\/counter['"];\n?/,""),n=n.replace(/<Counter\s*\/>\n?/g,""),await u(o,n)}}},_i=async(e,t)=>{if(!t.darkMode){await C(g.join(e,a.THEME_PROVIDER));let i=g.join(e,a.PROVIDERS_INDEX),r=await d(i);r=r.replace(/export \* from '\.\/CustomThemeProvider';\n/,""),await u(i,r);let s=g.join(e,a.GLOBALS_CSS);if(l(s)){let o=await d(s);o=o.replace(/@custom-variant dark \(.*?\);\n\n/,""),o=o.replace(/@theme \{[\s\S]*?\}\n/,""),await u(s,o)}if(!t.i18n){let o=g.join(e,a.ROOT_LAYOUT);if(l(o)){let n=await d(o);n=n.replace(/bg-light dark:bg-dark /g,""),await u(o,n)}}}},bi=async(e,t)=>{if(!t.i18n){await S(g.join(e,a.I18N_DIR)),await S(g.join(e,a.LOCALE_DIR)),await C(g.join(e,a.PROXY)),await C(g.join(e,a.MIDDLEWARE)),await C(g.join(e,a.I18N_TYPES)),await C(g.join(e,a.APP_LOCALES));let i=g.join(e,a.TYPES_INDEX);if(l(i)){let n=await d(i);n=n.replace(/export \* from '\.\/i18n';\n/,""),await u(i,n)}let r=g.join(e,a.CONFIG_INDEX);if(l(r)){let n=await d(r);n=n.replace(/export \* from '\.\/app-locales';\n/,""),await u(r,n)}let s=g.join(e,a.NEXT_CONFIG);if(l(s)){let n=await d(s);n=n.replace(/import createNextIntlPlugin from 'next-intl\/plugin';\n/,""),n=n.replace(/const withNextIntl = createNextIntlPlugin\(\);\n/,""),n=n.replace(/export default withNextIntl\(nextConfig\);/,"export default nextConfig;"),await u(s,n)}let o=g.join(e,a.COUNTER_COMPONENT);if(l(o)){let n=await d(o);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,"{value}"),n=n.replace(/\{t\(['"]increment['"]\)\}/g,"Increment"),n=n.replace(/\{t\(['"]decrement['"]\)\}/g,"Decrement"),n=n.replace(/\{t\(['"]reset['"]\)\}/g,"Reset"),await u(o,n)}}},Fi=async e=>{await C(g.join(e,a.LICENSE))},ji=async e=>{await C(g.join(e,a.CHANGELOG))},ki=async e=>{await C(g.join(e,a.NVM_RC)),await C(g.join(e,a.NPM_RC))};T();N();import be from"node:path";var it=async(e,t)=>{let i=[],r=[];t.redux&&(i.push("import { StoreProvider } from '@/providers';"),r.push("StoreProvider")),t.darkMode&&(i.push("import { CustomThemeProvider } from '@/providers';"),r.push("CustomThemeProvider")),t.i18n&&(i.push("import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';"),i.push("import { SupportedLocale } from '@/types/i18n';"));let s=`'use client';
16
- ${i.join(`
11
+ `,await u(t,r))}},Ve=async(e,o,t)=>{if(o===t)return;let r=o==="fetch"?"fetchClient":"axiosClient",n=t==="fetch"?"fetchClient":"axiosClient",i=o==="fetch"?"fetch-client":"axios-client",s=t==="fetch"?"fetch-client":"axios-client",c=R.join(e,"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 e=>{let o=R.join(e,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 t=R.join(e,a.TYPES_INDEX);if(l(t)){let r=await d(t),n=R.join(e,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(e,a.UTILITY_TYPES_DIR))||(r=r.replace(/^\s*export\s+\*\s+from\s+['"]\.\/utility['"];?.*$/gm,"")),await u(t,r)}},Gr=async(e,o,t=[])=>{let r=R.join(e,"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(e,x);return!t.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(e,o,t=[])=>{let r=R.join(e,"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(e,x);return!t.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 e=>{try{let o=Qe.join(e,"package.json"),t=await fi(o,"utf-8"),r=JSON.parse(t),n={...r.dependencies,...r.devDependencies},i=!!(n["@reduxjs/toolkit"]&&n["react-redux"]),s=!!n["next-intl"],c=!!n.axios,m=!1,f=Qe.join(e,"src","lib","utils","http","axios-client");try{await Kt(f)}catch{c=!1}let x=Qe.join(e,"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(e,o,t)=>{try{return await gi(Qt.join(e,t,o)),!0}catch{return!1}},Ae=(e,o,t)=>hi(Qt.join(e,o,t))});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(e="",o){let t=Sr({text:e,...o});return t.start(),t}import Cr from"enquirer";var{prompt:vr}=Cr,Et=async e=>{let o=await vr([{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 + 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: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(o.company=o.author,o.gitRemote&&!o.gitHomepage){let t=o.gitRemote.replace("git@github.com:","https://github.com/").replace(/\.git$/,"");o.gitHomepage=`${t}#readme`,o.gitIssues=`${t}/issues`}return o};w();import{exec as Tr}from"node:child_process";import{promisify as Er}from"node:util";var z=Er(Tr),Nt=async(e,o,t)=>{try{if(await z("git init",{cwd:e}),await z("git add .",{cwd:e}),await z('git commit -m "Initial commit from @teispace/next-maker"',{cwd:e}),o&&(await z(`git remote add origin ${o}`,{cwd:e}),t)){await z("git fetch origin",{cwd:e});let r="main";try{await z("git show-branch origin/main",{cwd:e})}catch{try{await z("git show-branch origin/master",{cwd:e}),r="master"}catch{r="main"}}await z(`git merge origin/${r} --allow-unrelated-histories -X ours`,{cwd:e}),await z(`git push origin HEAD:${r}`,{cwd:e})}}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(e,o)=>{let t=`${o} install`;try{await Ie(t,{cwd:e})}catch(r){throw new Error(`Failed to install dependencies with ${o}: ${r}`,{cause:r})}},D=async(e,o,t)=>{let r=o==="npm"?`${o} run ${t}`:`${o} ${t}`;try{await Ie(r,{cwd:e})}catch(n){console.warn(`Warning: Failed to run script '${t}': ${n}`)}},Rr=()=>{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"},U=async e=>{let{existsSync:o}=await import("node:fs"),t=await import("node:path");return o(t.join(e,"pnpm-lock.yaml"))?"pnpm":o(t.join(e,"yarn.lock"))?"yarn":o(t.join(e,"bun.lockb"))?"bun":o(t.join(e,"package-lock.json"))?"npm":Rr()},$r=async(e,o,t)=>{if(t.length===0)return;let n=`${Ar(o)} ${t.join(" ")}`;try{await Ie(n,{cwd:e})}catch(i){throw new Error(`Failed to install packages with ${o}: ${i}`,{cause:i})}},Ar=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"}},F=async(e,o)=>{let t=await U(e);await $r(e,t,[o])},br=async(e,o,t)=>{if(t.length===0)return;let n=`${Or(o)} ${t.join(" ")}`;try{await Ie(n,{cwd:e})}catch(i){throw new Error(`Failed to uninstall packages with ${o}: ${i}`,{cause:i})}},Or=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"}},Xe=async(e,o)=>{let t=await U(e);await br(e,t,[o])};import X from"picocolors";var kr={reset:e=>e,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(e,o="reset"){let t=kr[o]??(r=>r);console.log(t(e))}function Ne(e){oe(`\u2716 ${e}`,"red")}var C=Ne;function p(e){oe(e)}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(e){let{logger:o=s=>console.error(s),exitOnCancel:t=process.env.NODE_ENV!=="test"}=e??{},r=()=>{console.log(""),console.log(""),o("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"){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=e=>e.charAt(0).toUpperCase()+e.slice(1),k=e=>e.replace(/-([a-z])/g,(o,t)=>t.toUpperCase()),N=e=>_r(k(e));import jr from"ora";var g=jr();import Fr from"degit";var bt=async e=>{let o=A("Downloading template...");try{await Fr("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!0}).clone(e),o.succeed("Template downloaded successfully.")}catch(t){throw o.fail("Failed to download template."),t}};w();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(e,o)=>{let t=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(e,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)),t.succeed("package.json configured.")}catch(r){throw t.fail("Failed to configure package.json."),r}};w();T();Re();import E from"node:path";var jt=async(e,o)=>{let t=E.join(e,a.HTTP_UTILS),r=o.httpClient!=="none"||!!o.reactSecureStorage;o.httpClient==="none"?await Ur(e,t,r):o.httpClient==="axios"?await Xr(e,t):o.httpClient==="fetch"&&await Jr(e,t)},Ur=async(e,o,t)=>{await h(E.join(e,a.AXIOS_CLIENT)),await h(E.join(e,a.FETCH_CLIENT)),t?(await u(E.join(o,"index.ts"),`export * from './token-store';
15
+ `),await P(E.join(e,a.CLIENT_UTILS)),await ae(e,[])):(await h(o),await Yr(e),await P(E.join(e,a.APP_APIS)),await zr(e)),await Wr(e),await h(E.join(e,a.ERRORS_DIR)),t||(await h(E.join(e,a.COMMON_TYPES_DIR)),await h(E.join(e,a.UTILITY_TYPES_DIR)),await Br(e))},Xr=async(e,o)=>{await h(E.join(e,a.FETCH_CLIENT));let t=await d(E.join(o,"index.ts"));t=t.replace(/export .* from '\.\/fetch-client';\n/g,""),await u(E.join(o,"index.ts"),t);let r=E.join(e,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(e,o)=>{await h(E.join(e,a.AXIOS_CLIENT));let t=await d(E.join(o,"index.ts"));t=t.replace(/export .* from '\.\/axios-client';\n/g,""),await u(E.join(o,"index.ts"),t),await ae(e,["fetch"]);let r=E.join(e,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 e=>{let o=E.join(e,a.UTILS_INDEX);if(l(o)){let t=await d(o);t=t.replace(/export \* from '\.\/http';\n/,""),await u(o,t)}},zr=async e=>{let o=E.join(e,a.CONFIG_INDEX);if(l(o)){let t=await d(o);t=t.replace(/export \* from '\.\/app-apis';\n/,""),await u(o,t)}},Wr=async e=>{let o=E.join(e,a.CONSTANTS);if(l(o)){let t=await d(o);t=t.replace(/export const API_RESPONSE_DATA_KEY = 'data';\n/,""),t=t.replace(/export const SAVE_AUTH_TOKENS = false;\n/,""),await u(o,t)}},Br=async e=>{let o=E.join(e,a.TYPES_INDEX);if(l(o)){let t=await d(o);t=t.replace(/export \* from '\.\/utility';\n/,""),t=t.replace(/export \* from '\.\/common';\n/,""),await u(o,t)}};w();T();import ce from"node:path";var Ft=async(e,o)=>{o.redux||(await h(ce.join(e,a.STORE)),await h(ce.join(e,a.COUNTER_FEATURE)),await P(ce.join(e,a.STORE_PROVIDER)),await Vr(e),await qr(e))},Vr=async e=>{let o=ce.join(e,a.PROVIDERS_INDEX),t=await d(o);t=t.replace(/export \* from '\.\/StoreProvider';\n/,""),await u(o,t)},qr=async e=>{let o=[ce.join(e,a.ROOT_PAGE),ce.join(e,a.LOCALE_PAGE)];for(let t of o)if(l(t)){let r=await d(t);r=r.replace(/import\s+\{\s*Counter\s*\}\s+from\s+['"]@\/features\/counter['"];\n?/,""),r=r.replace(/<Counter\s*\/>\n?/g,""),await u(t,r)}};w();T();import $e from"node:path";var Dt=async(e,o)=>{o.darkMode||(await P($e.join(e,a.THEME_PROVIDER)),await Kr(e),await Zr(e),o.i18n||await Qr(e))},Kr=async e=>{let o=$e.join(e,a.PROVIDERS_INDEX),t=await d(o);t=t.replace(/export \* from '\.\/CustomThemeProvider';\n/,""),await u(o,t)},Zr=async e=>{let o=$e.join(e,a.GLOBALS_CSS);if(l(o)){let t=await d(o);t=t.replace(/@custom-variant dark \(.*?\);\n\n/,""),t=t.replace(/@theme \{[\s\S]*?\}\n/,""),await u(o,t)}},Qr=async e=>{let o=$e.join(e,a.ROOT_LAYOUT);if(l(o)){let t=await d(o);t=t.replace(/bg-light dark:bg-dark /g,""),await u(o,t)}};w();T();import J from"node:path";var Lt=async(e,o)=>{o.i18n||(await ei(e),await ti(e),await oi(e),await ri(e))},ei=async e=>{await h(J.join(e,a.I18N_DIR)),await h(J.join(e,a.LOCALE_DIR)),await P(J.join(e,a.PROXY)),await P(J.join(e,a.MIDDLEWARE)),await P(J.join(e,a.I18N_TYPES)),await P(J.join(e,a.APP_LOCALES))},ti=async e=>{let o=J.join(e,a.TYPES_INDEX);if(l(o)){let r=await d(o);r=r.replace(/export \* from '\.\/i18n';\n/,""),await u(o,r)}let t=J.join(e,a.CONFIG_INDEX);if(l(t)){let r=await d(t);r=r.replace(/export \* from '\.\/app-locales';\n/,""),await u(t,r)}},oi=async e=>{let o=J.join(e,a.NEXT_CONFIG);if(l(o)){let t=await d(o);t=t.replace(/import createNextIntlPlugin from 'next-intl\/plugin';\n/,""),t=t.replace(/const withNextIntl = createNextIntlPlugin\(\);\n/,""),t=t.replace(/export default withNextIntl\(nextConfig\);/,"export default nextConfig;"),await u(o,t)}},ri=async e=>{let o=J.join(e,a.COUNTER_COMPONENT);if(l(o)){let t=await d(o);t=t.replace(/import\s+\{\s*useTranslations\s*\}\s+from\s+['"]next-intl['"];\n/,""),t=t.replace(/\s*const\s+t\s*=\s*useTranslations\(['"]Count['"]\);\n/,""),t=t.replace(/\{t\('currentCount',\s*\{\s*count:\s*value\s*\}\)\}/g,"{value}"),t=t.replace(/\{t\(['"]increment['"]\)\}/g,"Increment"),t=t.replace(/\{t\(['"]decrement['"]\)\}/g,"Decrement"),t=t.replace(/\{t\(['"]reset['"]\)\}/g,"Reset"),await u(o,t)}};w();T();import K from"node:path";var Ht=async(e,o)=>{o.httpClient!=="none"||o.reactSecureStorage||await P(K.join(e,a.STORAGE_SERVICE))},Gt=async e=>{await P(K.join(e,a.LICENSE))},Mt=async e=>{await P(K.join(e,a.CHANGELOG))},Ut=async e=>{await P(K.join(e,a.NVM_RC)),await P(K.join(e,a.NPM_RC))},Xt=async e=>{await h(K.join(e,a.CLAUDE_DIR)),await h(K.join(e,a.DOCS_DIR)),await h(K.join(e,a.VSCODE_DIR))};var Jt=async(e,o)=>{let t=A("Customizing features...");try{await jt(e,o),await Ht(e,o),await Ft(e,o),await Dt(e,o),await Lt(e,o),await Gt(e),await Mt(e),await Ut(e),await Xt(e),t.succeed("Features customized.")}catch(r){throw t.fail("Failed to customize features."),r}};w();T();import Ke from"node:path";var Yt=async(e,o)=>{let t=[],r=[];o.redux&&(t.push("import { StoreProvider } from '@/providers';"),r.push("StoreProvider")),o.darkMode&&(t.push("import { CustomThemeProvider } from '@/providers';"),r.push("CustomThemeProvider")),o.i18n&&(t.push("import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';"),t.push("import { SupportedLocale } from '@/types/i18n';"));let n=`'use client';
16
+ ${t.join(`
17
17
  `)}
18
18
 
19
19
  export const RootProvider = ({
20
20
  children,
21
- ${t.i18n?`locale,
21
+ ${o.i18n?`locale,
22
22
  messages,`:""}
23
23
  }: {
24
24
  children: React.ReactNode;
25
- ${t.i18n?`locale: SupportedLocale;
25
+ ${o.i18n?`locale: SupportedLocale;
26
26
  messages: AbstractIntlMessages;`:""}
27
27
  }) => {
28
28
  return (
29
- `,o="{children}";t.i18n&&(o=`<NextIntlClientProvider locale={locale} messages={messages}>
30
- ${o}
31
- </NextIntlClientProvider>`),t.darkMode&&(o=`<CustomThemeProvider>
32
- ${o}
33
- </CustomThemeProvider>`),t.redux&&(o=`<StoreProvider>
34
- ${o}
35
- </StoreProvider>`),o==="{children}"&&(o="<>{children}</>"),s+=` ${o}
29
+ `,i="{children}";o.i18n&&(i=`<NextIntlClientProvider locale={locale} messages={messages}>
30
+ ${i}
31
+ </NextIntlClientProvider>`),o.darkMode&&(i=`<CustomThemeProvider>
32
+ ${i}
33
+ </CustomThemeProvider>`),o.redux&&(i=`<StoreProvider>
34
+ ${i}
35
+ </StoreProvider>`),i==="{children}"&&(i="<>{children}</>"),n+=` ${i}
36
36
  );
37
37
  };
38
- `,await u(be.join(e,a.ROOT_PROVIDER),s)},ot=async(e,t)=>{if(!t.i18n){let i=`import type { Metadata } from 'next';
38
+ `,await u(Ke.join(e,a.ROOT_PROVIDER),n)},zt=async(e,o)=>{if(!o.i18n){let t=`import type { Metadata } from 'next';
39
39
  import '@/styles/globals.css';
40
40
  import { Livvic } from 'next/font/google';
41
41
  import { RootProvider } from '@/providers';
@@ -48,8 +48,8 @@ const livvic = Livvic({
48
48
  });
49
49
 
50
50
  export const metadata: Metadata = {
51
- title: '${t.projectName}',
52
- description: '${t.description}',
51
+ title: '${o.projectName}',
52
+ description: '${o.description}',
53
53
  };
54
54
 
55
55
  export default function RootLayout({
@@ -58,8 +58,8 @@ export default function RootLayout({
58
58
  children: React.ReactNode;
59
59
  }>) {
60
60
  return (
61
- <html lang="en" suppressHydrationWarning={${t.darkMode?"true":"false"}}>
62
- <body className={\`\${livvic.variable} ${t.darkMode?"bg-light dark:bg-dark ":""}antialiased\`}>
61
+ <html lang="en" suppressHydrationWarning={${o.darkMode?"true":"false"}}>
62
+ <body className={\`\${livvic.variable} ${o.darkMode?"bg-light dark:bg-dark ":""}antialiased\`}>
63
63
  <RootProvider>
64
64
  {children}
65
65
  </RootProvider>
@@ -67,55 +67,55 @@ export default function RootLayout({
67
67
  </html>
68
68
  );
69
69
  }
70
- `;await u(be.join(e,a.ROOT_LAYOUT),i);let r=t.redux?`import { Counter } from '@/features/counter';
70
+ `;await u(Ke.join(e,a.ROOT_LAYOUT),t);let r=o.redux?`import { Counter } from '@/features/counter';
71
71
 
72
- `:"",s=t.redux?`
73
- <Counter />`:"",o=`${r}export default function Home() {
72
+ `:"",n=o.redux?`
73
+ <Counter />`:"",i=`${r}export default function Home() {
74
74
  return (
75
75
  <div className="flex min-h-screen flex-col items-center justify-center p-24">
76
- <h1 className="text-4xl font-bold">Welcome to ${t.projectName}</h1>
77
- <p className="mt-4 text-xl">Get started by editing src/app/page.tsx</p>${s}
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}
78
78
  </div>
79
79
  );
80
80
  }
81
- `;await u(be.join(e,a.ROOT_PAGE),o)}};T();N();import E from"node:path";import{readdir as rt}from"node:fs/promises";var nt=async(e,t)=>{await Di(e,t),await Li(e,t),await Mi(e,t),await Hi(e,t),await Gi(e,t),await Ui(e,t),await Yi(e,t)},Di=async(e,t)=>{t.preCommitHooks||(await S(E.join(e,a.HUSKY_DIR)),await C(E.join(e,a.COMMITLINT_CONFIG)),await C(E.join(e,a.LINTSTAGED_RC)),await ne(E.join(e,a.PACKAGE_JSON),i=>(delete i.devDependencies[_.HUSKY],delete i.devDependencies[_.COMMITLINT_CLI],delete i.devDependencies[_.COMMITLINT_CONFIG],delete i.devDependencies[_.LINT_STAGED],delete i.scripts.prepare,delete i.scripts.postinstall,delete i.commitlint,delete i["lint-staged"],i)))},Li=async(e,t)=>{t.commitizen||(await C(E.join(e,a.CZRC)),await ne(E.join(e,a.PACKAGE_JSON),i=>(delete i.devDependencies[_.COMMITIZEN],delete i.devDependencies[_.CZ_CONVENTIONAL_CHANGELOG],delete i.config?.commitizen,i.config&&Object.keys(i.config).length===0&&delete i.config,delete i.scripts.commit,i)))},Mi=async(e,t)=>{t.ci||await S(E.join(e,a.GITHUB_WORKFLOWS))},Hi=async(e,t)=>{let i=E.join(e,a.GITHUB_DIR);if(!t.keepTemplates)await S(E.join(i,a.GITHUB_ISSUE_TEMPLATE)),await C(E.join(i,a.GITHUB_PR_TEMPLATE));else{let r=E.join(i,a.GITHUB_ISSUE_TEMPLATE),s=E.join(i,a.GITHUB_PR_TEMPLATE),o=n=>n.replace(/Teispace/g,t.company).replace(/support@teispace\.com/g,t.email).replace(/Next\.js Starter/g,t.projectName).replace(/\[AUTHOR\]/g,t.author).replace(/\[COMPANY\]/g,t.company).replace(/\[EMAIL\]/g,t.email);if(l(s)){let n=await d(s);n=o(n),await u(s,n)}try{if(l(r)){let n=await rt(r);for(let c of n){let p=E.join(r,c),m=await d(p);m=o(m),await u(p,m)}}}catch{}}},Gi=async(e,t)=>{let i=[a.CODE_OF_CONDUCT,a.CONTRIBUTING,a.SECURITY];for(let r of i)t.communityFiles.includes(r)||await C(E.join(e,r))},Ui=async(e,t)=>{if(t.docker){let i=E.join(e,a.ENV_EXAMPLE);if(l(i)){let r=await d(i),s=(o,n)=>{let c=new RegExp(`${o}=.*`);c.test(r)?r=r.replace(c,`${o}=${n}`):r+=`${o}=${n}
82
- `};s("CONTAINER_NAME",t.containerName||"next-app"),s("IMAGE_NAME",t.imageName||"nextjs-starter"),s("IMAGE_TAG",t.imageTag||"latest"),await u(i,r)}}else{await C(E.join(e,a.DOCKERFILE)),await C(E.join(e,a.DOCKER_COMPOSE)),await C(E.join(e,a.DOCKERIGNORE));let i=E.join(e,a.ENV_EXAMPLE);if(l(i)){let r=await d(i);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(i,r)}}},Yi=async(e,t)=>{let i=async o=>{let n=await rt(o,{withFileTypes:!0}),c=[];for(let p of n){let m=E.join(o,p.name);p.isDirectory()&&p.name!=="node_modules"&&p.name!==".git"?c.push(...await i(m)):p.isFile()&&p.name.toLowerCase()==="readme.md"&&c.push(m)}return c},r=await i(e),s=E.join(e,a.README);for(let o of r)o!==s&&await C(o);if(t.readme){let o=`# ${t.projectName}
81
+ `;await u(Ke.join(e,a.ROOT_PAGE),i)}};w();T();import I from"node:path";import{readdir as Wt}from"node:fs/promises";var Bt=async(e,o)=>{await ii(e,o),await ni(e,o),await si(e,o),await ai(e,o),await ci(e,o),await pi(e,o),await mi(e,o)},ii=async(e,o)=>{o.preCommitHooks||(await h(I.join(e,a.HUSKY_DIR)),await P(I.join(e,a.COMMITLINT_CONFIG)),await P(I.join(e,a.LINTSTAGED_RC)),await me(I.join(e,a.PACKAGE_JSON),t=>(delete t.devDependencies[b.HUSKY],delete t.devDependencies[b.COMMITLINT_CLI],delete t.devDependencies[b.COMMITLINT_CONFIG],delete t.devDependencies[b.LINT_STAGED],delete t.scripts.prepare,delete t.scripts.postinstall,delete t.commitlint,delete t["lint-staged"],t)))},ni=async(e,o)=>{o.commitizen||(await P(I.join(e,a.CZRC)),await me(I.join(e,a.PACKAGE_JSON),t=>(delete t.devDependencies[b.COMMITIZEN],delete t.devDependencies[b.CZ_CONVENTIONAL_CHANGELOG],delete t.config?.commitizen,t.config&&Object.keys(t.config).length===0&&delete t.config,delete t.scripts.commit,t)))},si=async(e,o)=>{o.ci||await h(I.join(e,a.GITHUB_WORKFLOWS))},ai=async(e,o)=>{let t=I.join(e,a.GITHUB_DIR);if(!o.keepTemplates)await h(I.join(t,a.GITHUB_ISSUE_TEMPLATE)),await P(I.join(t,a.GITHUB_PR_TEMPLATE));else{let r=I.join(t,a.GITHUB_ISSUE_TEMPLATE),n=I.join(t,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(e,o)=>{let t=[a.CODE_OF_CONDUCT,a.CONTRIBUTING,a.SECURITY];for(let r of t)o.communityFiles.includes(r)||await P(I.join(e,r))},pi=async(e,o)=>{if(o.docker){let t=I.join(e,a.ENV_EXAMPLE);if(l(t)){let r=await d(t),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(t,r)}}else{await P(I.join(e,a.DOCKERFILE)),await P(I.join(e,a.DOCKER_COMPOSE)),await P(I.join(e,a.DOCKERIGNORE));let t=I.join(e,a.ENV_EXAMPLE);if(l(t)){let r=await d(t);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(t,r)}}},mi=async(e,o)=>{let t=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 t(f)):m.isFile()&&m.name.toLowerCase()==="readme.md"&&c.push(f)}return c},r=await t(e),n=I.join(e,a.README);for(let i of r)i!==n&&await P(i);if(o.readme){let i=`# ${o.projectName}
83
83
 
84
- ${t.description}
84
+ ${o.description}
85
85
 
86
86
  ## Getting Started
87
87
 
88
88
  First, run the development server:
89
89
 
90
90
  \`\`\`bash
91
- ${t.packageManager==="npm"?"npm run dev":t.packageManager+" dev"}
91
+ ${o.packageManager==="npm"?"npm run dev":o.packageManager+" dev"}
92
92
  \`\`\`
93
93
 
94
94
  Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
95
- `;await u(s,o)}else await C(s)};var st=e=>{e.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async t=>{await Xi(t)})},Xi=async e=>{Ke(),f("Welcome to the Teispace Next.js App Creator!"),f("");let t=await Je(e),i=Fe.resolve(process.cwd(),t.projectName);l(i)&&(console.error(K.red(`Error: Directory ${t.projectName} already exists.`)),process.exit(1));let r=$("Initializing project..."),s=async()=>{if(l(i)){r.stop(),console.log(K.yellow(`
96
- Cleaning up: Deleting directory ${t.projectName}...`));try{await S(i),console.log(K.green("Cleanup successful."))}catch(n){console.error(K.red(`Failed to clean up directory ${t.projectName}:`),n)}}},o=async()=>{console.log(K.red(`
97
- Process interrupted. Cleaning up...`)),await s(),process.exit(1)};process.on("SIGINT",o),process.on("SIGTERM",o);try{if(await qe(i),await Qe(i,t),await tt(i,t),r.text="Generating code...",await it(i,t),await ot(i,t),r.text="Setting up developer tools...",await nt(i,t),r.text="Initializing Git...",await ze(i,t.gitRemote,t.pushToRemote),r.text="Installing dependencies...",await Ve(i,t.packageManager),r.text="Formatting and Linting...",await H(i,t.packageManager,"format"),await H(i,t.packageManager,"lint:fix"),t.copyEnv){r.text="Creating .env file...";let n=Fe.join(i,".env.example"),c=Fe.join(i,".env");l(n)&&await(await import("node:fs/promises")).copyFile(n,c)}process.off("SIGINT",o),process.off("SIGTERM",o),r.succeed(K.green(`Project ${t.projectName} created successfully!`)),f(""),f("To get started:"),f(K.cyan(` cd ${t.projectName}`)),f(K.cyan(` ${t.packageManager==="npm"?"npm run dev":t.packageManager+" dev"}`)),f("")}catch(n){r.fail("Failed to create project."),console.error(n),await s(),process.exit(1)}};import O from"picocolors";import De from"node:path";import Ji from"enquirer";var{prompt:Wi}=Ji,at=async(e,t,i,r,s,o,n)=>{let c=[];e||c.push({type:"input",name:"featureName",message:"What is the feature name?",initial:"my-feature",validate:m=>/^[a-z0-9-]+$/.test(m)?!0:"Feature name must be lowercase and contain only alphanumeric characters and hyphens."}),t&&r===void 0&&s===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}})),i&&i!=="none"&&o===void 0&&n===void 0&&(c.push({type:"confirm",name:"createService",message:"Generate API service for this feature?",initial:!0}),i==="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 Wi(c):{};return{featureName:e||p.featureName,hasRedux:t||!1,createStore:r===!0?!1:s!==void 0?!0:p.createStore||!1,persistStore:s==="persist"?!0:s==="no-persist"?!1:p.persistStore||!1,httpClient:i||"none",createService:o===!0?!1:n!==void 0?!0:p.createService||!1,selectedHttpClient:n||p.selectedHttpClient||(i==="both"?"fetch":i!=="none"?i:void 0)}};import{readFile as zi,access as je}from"node:fs/promises";import se from"node:path";var re=async e=>{let t=!1,i=!1,r=!1,s=!1;try{let o=se.join(e,"package.json"),n=await zi(o,"utf-8"),c=JSON.parse(n),p={...c.dependencies,...c.devDependencies};t=!!(p["@reduxjs/toolkit"]&&p["react-redux"]),i=!!p.axios,s=!!p["next-intl"];let m=se.join(e,"src","lib","utils","http","axios-client");try{await je(m),i=i&&!0}catch{i=!1}let h=se.join(e,"src","lib","utils","http","fetch-client");try{await je(h),r=!0}catch{r=!1}let y;return i&&r?y="both":i?y="axios":r?y="fetch":y="none",{hasRedux:t,httpClient:y,hasI18n:s}}catch(o){throw new Error(`Failed to detect project setup: ${o}`)}},ct=async(e,t,i=se.join("src","features"))=>{let r=se.join(e,i,t);try{return await je(r),!0}catch{return!1}};import{writeFile as X,mkdir as ae}from"node:fs/promises";import j from"node:path";var lt=async e=>{let{featurePath:t}=e;await ae(j.join(t,"components"),{recursive:!0}),await ae(j.join(t,"hooks"),{recursive:!0}),await ae(j.join(t,"types"),{recursive:!0}),e.createStore&&await ae(j.join(t,"store"),{recursive:!0}),e.createService&&await ae(j.join(t,"services"),{recursive:!0}),await Vi(e),await Ki(e),await Bi(e),await Qi(e),e.createStore&&await qi(e),e.createService&&e.httpClient&&await Zi(e)};var Vi=async e=>{let{featureName:t,featurePath:i}=e,r=V(t),s=`use${r}`,o=`'use client';
98
- import { ${s} } from '../hooks/${s}';
95
+ `;await u(n,i)}else await P(n)};var Vt=e=>{e.command("init").description("Initialize a new Next.js project").argument("[name]","Project name").action(async o=>{await li(o)})},li=async e=>{$t(),p("Welcome to the Teispace Next.js App Creator!"),p("");let o=await Et(e),t=Ze.resolve(process.cwd(),o.projectName);l(t)&&(console.error(Z.red(`Error: Directory ${o.projectName} already exists.`)),process.exit(1));let r=A("Initializing project..."),n=async()=>{if(l(t)){r.stop(),console.log(Z.yellow(`
96
+ Cleaning up: Deleting directory ${o.projectName}...`));try{await h(t),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(t),await kt(t,o),await Jt(t,o),r.text="Generating code...",await Yt(t,o),await zt(t,o),r.text="Setting up developer tools...",await Bt(t,o),r.text="Initializing Git...",await Nt(t,o.gitRemote,o.pushToRemote),r.text="Installing dependencies...",await Rt(t,o.packageManager),r.text="Formatting and Linting...",await D(t,o.packageManager,"format"),await D(t,o.packageManager,"lint:fix"),o.copyEnv){r.text="Creating .env file...";let s=Ze.join(t,".env.example"),c=Ze.join(t,".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(e,o,t,r,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."}),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}})),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 m=c.length>0?await ui(c):{};return{featureName:e||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:t||"none",createService:i===!0?!1:s!==void 0?!0:m.createService||!1,selectedHttpClient:s||m.selectedHttpClient||(t==="both"?"fetch":t!=="none"?t:void 0)}};W();var re=async(e,o)=>{for(let t of e)if(!t.shouldSkip?.(o)){o.spinner.start(t.spinnerText);try{await t.execute(o),o.spinner.succeed(t.name)}catch(r){throw o.spinner.fail(t.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=e=>{let{componentName:o,hookName:t}=e;return`'use client';
98
+ import { ${t} } from '../hooks/${t}';
99
99
 
100
- export function ${r}() {
101
- const {} = ${s}();
100
+ export function ${o}() {
101
+ const {} = ${t}();
102
102
 
103
103
  return (
104
104
  <div>
105
- <h2>${r} Component</h2>
105
+ <h2>${o} Component</h2>
106
106
  {/* Add your component UI here */}
107
107
  </div>
108
108
  );
109
109
  }
110
110
 
111
- export default ${r};
112
- `;await X(j.join(i,"components",`${r}.tsx`),o)},Ki=async e=>{let{featureName:t,featurePath:i,createStore:r}=e,s=V(t),o=`use${s}`,n;r?n=`'use client';
111
+ export default ${o};
112
+ `};var ro=e=>{let{hookName:o,componentName:t,featureName:r}=e;return`'use client';
113
113
  import { useAppDispatch, useAppSelector } from '@/store/hooks';
114
- import { select${s}State, setLoading, setError } from '../store/${t}.selectors';
114
+ import { select${t}State, setLoading, setError } from '../store/${r}.selectors';
115
115
 
116
116
  export const ${o} = () => {
117
117
  const dispatch = useAppDispatch();
118
- const state = useAppSelector(select${s}State);
118
+ const state = useAppSelector(select${t}State);
119
119
 
120
120
  const handleSetLoading = (loading: boolean) => {
121
121
  dispatch(setLoading(loading));
@@ -133,7 +133,7 @@ export const ${o} = () => {
133
133
  setError: handleSetError,
134
134
  } as const;
135
135
  };
136
- `:n=`'use client';
136
+ `},io=e=>{let{hookName:o}=e;return`'use client';
137
137
  import { useState } from 'react';
138
138
 
139
139
  export const ${o} = () => {
@@ -145,22 +145,32 @@ export const ${o} = () => {
145
145
  // Add your methods here
146
146
  } as const;
147
147
  };
148
- `,await X(j.join(i,"hooks",`${o}.ts`),n)},Bi=async e=>{let{featureName:t,featurePath:i,createStore:r}=e,n=`export interface ${`${V(t)}State`} {
149
- // Add your state properties here
150
- ${r?`loading: boolean;
151
- error: string | null;`:"// example: value: string;"}
148
+ `};var be=e=>{let{componentName:o,withStore:t}=e;return`export interface ${o}State {
149
+ ${t?`loading: boolean;
150
+ error: string | null;
151
+ // Add your state properties here`:`// Add your state properties here
152
+ // example: value: string;`}
152
153
  }
153
- `;await X(j.join(i,"types",`${t}.types.ts`),n)},qi=async e=>{let{featureName:t,featurePath:i,persistStore:r}=e,s=V(t),o=L(t),n=`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
154
- import { ${s}State } from '../types/${t}.types';
155
-
156
- const initialState: ${s}State = {
154
+ `};var no=e=>{let{sliceName:o,withPersist:t}=e;return`export * from './${o}.slice';
155
+ export * from './${o}.selectors';
156
+ export * from './${o}.types';${t?`
157
+ export * from './persist';`:""}
158
+ `},so=e=>{let{featureName:o,componentName:t,hookName:r,withStore:n,withService:i}=e;return`export { default as ${t} } from './components/${t}';
159
+ export { ${r} } from './hooks/${r}';
160
+ export * from './types/${o}.types';${n?`
161
+ 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=e=>{let{componentName:o,camelName:t,typesImportPath:r}=e;return`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
164
+ import { ${o}State } from '${r}';
165
+
166
+ const initialState: ${o}State = {
157
167
  loading: false,
158
168
  error: null,
159
169
  // Add your initial state here
160
170
  };
161
171
 
162
- export const ${o}Slice = createSlice({
163
- name: '${o}',
172
+ export const ${t}Slice = createSlice({
173
+ name: '${t}',
164
174
  initialState,
165
175
  reducers: {
166
176
  setLoading: (state, action: PayloadAction<boolean>) => {
@@ -176,203 +186,292 @@ export const ${o}Slice = createSlice({
176
186
  },
177
187
  });
178
188
 
179
- export const { setLoading, setError, resetState } = ${o}Slice.actions;
189
+ export const { setLoading, setError, resetState } = ${t}Slice.actions;
180
190
 
181
- export const ${o}Reducer = ${o}Slice.reducer;
182
- `;await X(j.join(i,"store",`${t}.slice.ts`),n);let c=`import { RootState } from '@/store/rootReducer';
191
+ export const ${t}Reducer = ${t}Slice.reducer;
192
+ `};var co=e=>{let{componentName:o,camelName:t,sliceName:r}=e;return`import { RootState } from '@/store/rootReducer';
183
193
 
184
- export const select${s}State = (state: RootState) => state.${o};
185
- export { setLoading, setError, resetState } from './${t}.slice';
186
- `;if(await X(j.join(i,"store",`${t}.selectors.ts`),c),r){let m=`import { PersistConfig } from 'redux-persist';
194
+ export const select${o}State = (state: RootState) => state.${t};
195
+ export { setLoading, setError, resetState } from './${r}.slice';
196
+ `};var po=e=>{let{componentName:o,camelName:t,typesImportPath:r}=e;return`import { PersistConfig } from 'redux-persist';
187
197
  import storage from 'redux-persist/lib/storage';
188
- import { ${s}State } from '../types/${t}.types';
198
+ import { ${o}State } from '${r}';
189
199
 
190
- export const ${o}PersistConfig: PersistConfig<${s}State> = {
191
- key: '${o}',
200
+ export const ${t}PersistConfig: PersistConfig<${o}State> = {
201
+ key: '${t}',
192
202
  storage,
193
203
  // whitelist: ['someField'], // Specify which fields to persist
194
204
  };
195
- `;await X(j.join(i,"store","persist.ts"),m)}let p=`export * from './${t}.slice';
196
- export * from './${t}.selectors';${r?`
197
- export * from './persist';`:""}
198
- `;await X(j.join(i,"store","index.ts"),p)},Zi=async e=>{let{featureName:t,featurePath:i,httpClient:r}=e,s=L(t),o;r==="axios"?o=`import { AppApis } from '@/lib/config';
199
- import { axiosClient } from '@/lib/utils/http';
205
+ `};var ue=async e=>{let{name:o,outputPath:t,persist:r,typesImportPath:n=`./${o}.types`}=e;await xi(t,{recursive:!0});let i=N(o),s=k(o);await Promise.all([le(de.join(t,`${o}.types.ts`),be({componentName:i,withStore:!0})),le(de.join(t,`${o}.slice.ts`),ao({componentName:i,camelName:s,typesImportPath:n})),le(de.join(t,`${o}.selectors.ts`),co({componentName:i,camelName:s,sliceName:o})),...r?[le(de.join(t,"persist.ts"),po({componentName:i,camelName:s,typesImportPath:n}))]:[],le(de.join(t,"index.ts"),no({sliceName:o,withPersist:r}))])};import{writeFile as yi}from"node:fs/promises";import Pi from"node:path";var mo=e=>{let{camelName:o,httpClient:t}=e;return`import { AppApis } from '@/lib/config';
206
+ ${t==="axios"?"import { axiosClient } from '@/lib/utils/http';":"import { fetchClient } from '@/lib/utils/http';"}
200
207
  import { ResultAsync } from '@/types';
201
208
 
202
- export const ${s}Service = {
209
+ export const ${o}Service = {
203
210
  getAll: (): ResultAsync<string> => {
204
- return axiosClient.get<string>(AppApis.${s}.getAll);
211
+ return ${t==="axios"?"axiosClient":"fetchClient"}.get<string>(AppApis.${o}.getAll);
205
212
  },
206
213
  };
207
- `:o=`import { AppApis } from '@/lib/config';
208
- import { fetchClient } from '@/lib/utils/http';
214
+ `};var fe=async e=>{let{name:o,outputPath:t,httpClient:r}=e,n=k(o);await yi(Pi.join(t,`${o}.service.ts`),mo({camelName:n,httpClient:r}))};var et=async e=>{let{name:o,outputPath:t,createStore:r,persistStore:n,createService:i,httpClient:s}=e,c=N(o),m=`use${c}`,f=[L.join(t,"components"),L.join(t,"hooks"),L.join(t,"types"),...r?[L.join(t,"store")]:[],...i?[L.join(t,"services")]:[]];await Promise.all(f.map(x=>wi(x,{recursive:!0}))),await Promise.all([Oe(L.join(t,"components",`${c}.tsx`),oo({componentName:c,hookName:m})),Oe(L.join(t,"hooks",`${m}.ts`),r?ro({hookName:m,componentName:c,featureName:o}):io({hookName:m})),Oe(L.join(t,"types",`${o}.types.ts`),be({componentName:c,withStore:r})),Oe(L.join(t,"index.ts"),so({featureName:o,componentName:c,hookName:m,withStore:r,withService:i}))]),r&&await ue({name:o,outputPath:L.join(t,"store"),persist:n,typesImportPath:`../types/${o}.types`}),i&&s&&await fe({name:o,outputPath:L.join(t,"services"),httpClient:s})};import{writeFile as Si}from"node:fs/promises";import Ci from"node:path";var lo=e=>{let{camelName:o,pascalName:t,httpClient:r}=e,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}
209
216
  import { ResultAsync } from '@/types';
210
217
 
211
- export const ${s}Service = {
212
- getAll: (): ResultAsync<string> => {
213
- return fetchClient.get<string>(AppApis.${s}.getAll);
218
+ export interface ${t} {
219
+ id: string;
220
+ // Add your ${o} properties here
221
+ }
222
+
223
+ export interface Create${t}Dto {
224
+ // Add create fields here
225
+ }
226
+
227
+ export interface Update${t}Dto {
228
+ // Add update fields here
229
+ }
230
+
231
+ export const ${o}Service = {
232
+ getAll: (): ResultAsync<${t}[]> => {
233
+ return ${i}.get<${t}[]>(AppApis.${o}.getAll);
234
+ },
235
+
236
+ getById: (id: string): ResultAsync<${t}> => {
237
+ return ${i}.get<${t}>(AppApis.${o}.getById(id));
238
+ },
239
+
240
+ create: (data: Create${t}Dto): ResultAsync<${t}> => {
241
+ return ${i}.post<${t}>(AppApis.${o}.create, data);
242
+ },
243
+
244
+ update: (id: string, data: Update${t}Dto): ResultAsync<${t}> => {
245
+ return ${i}.patch<${t}>(AppApis.${o}.update(id), data);
246
+ },
247
+
248
+ delete: (id: string): ResultAsync<void> => {
249
+ return ${i}.delete<void>(AppApis.${o}.delete(id));
214
250
  },
215
251
  };
216
- `,await X(j.join(i,"services",`${t}.service.ts`),o)},Qi=async e=>{let{featureName:t,featurePath:i,createStore:r,createService:s}=e,o=V(t),n=`export { default as ${o} } from './components/${o}';
217
- export { use${o} } from './hooks/use${o}';
218
- export * from './types/${t}.types';${r?`
219
- export * from './store';`:""}${s?`
220
- export * from './services/${t}.service';`:""}
221
- `;await X(j.join(i,"index.ts"),n)};import{readFile as pt,writeFile as mt}from"node:fs/promises";import ke from"node:path";var dt=async(e,t,i,r=ke.join("src","features"))=>{let s=ke.join(e,"src","store","rootReducer.ts");try{let o=await pt(s,"utf-8"),n=L(t),c=`${n}Reducer`,p=i?`${n}PersistConfig`:"",m=r.replace(/^src\//,"@/"),h=i?`import { ${c}, ${p} } from '${m}/${t}/store';`:`import { ${c} } from '${m}/${t}/store';`,y=/import\s+.*\s+from\s+['"].*['"];?\n/g,x=o.match(y);if(x&&x.length>0){let I=x[x.length-1],F=o.lastIndexOf(I);o=o.slice(0,F+I.length)+h+`
222
- `+o.slice(F+I.length)}else o=h+`
223
- `+o;let w=/combineReducers\(\{([^}]*)\}\)/s,D=o.match(w);if(D){let I=D[1],F=i?`
224
- ${n}: persistReducer(${p}, ${c}),`:`
225
- ${n}: ${c},`,ie=I.trimEnd()+F;o=o.replace(w,`combineReducers({${ie}
226
- })`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await mt(s,o)}catch(o){throw new Error(`Failed to register feature in rootReducer: ${o}`)}},ut=async(e,t,i,r)=>{let s=ke.join(e,"src","store","rootReducer.ts");try{let o=await pt(s,"utf-8"),n=L(t),c=`${n}Reducer`,p=i?`${n}PersistConfig`:"",m=r.replace(/^src\//,"@/"),h=i?`import { ${c}, ${p} } from '${m}/${t}';`:`import { ${c} } from '${m}/${t}';`,y=/import\s+.*\s+from\s+['"].*['"];?\n/g,x=o.match(y);if(x&&x.length>0){let I=x[x.length-1],F=o.lastIndexOf(I);o=o.slice(0,F+I.length)+h+`
227
- `+o.slice(F+I.length)}else o=h+`
228
- `+o;let w=/combineReducers\(\{([^}]*)\}\)/s,D=o.match(w);if(D){let I=D[1],F=i?`
229
- ${n}: persistReducer(${p}, ${c}),`:`
230
- ${n}: ${c},`,ie=I.trimEnd()+F;o=o.replace(w,`combineReducers({${ie}
231
- })`)}else throw new Error("Could not find combineReducers in rootReducer.ts");await mt(s,o)}catch(o){throw new Error(`Failed to register slice in rootReducer: ${o}`)}};import{readFile as eo,writeFile as to}from"node:fs/promises";import io from"node:path";var ge=async e=>{let{serviceName:t,projectPath:i}=e,r=L(t),s=io.join(i,"src","lib","config","app-apis.ts");try{let o=await eo(s,"utf-8");if(o.includes(`${r}:`))return;if(!o.match(/export const AppApis = \{[\s\S]*?\} as const;/))throw new Error("Could not find AppApis object in app-apis.ts");let c=` ${r}: {
252
+ `},uo=e=>{let{camelName:o,kebabName:t}=e;return` ${o}: {
232
253
  base: \`\${API_PREFIX}/${t}\`,
233
254
  getAll: \`\${API_PREFIX}/${t}\`,
234
- },`,p=/(\s*)\} as const;/;if(!o.match(p))throw new Error("Could not find closing brace of AppApis object");let h=o.lastIndexOf("} as const;"),y=o.substring(0,h),x=o.substring(h),w=y.trim().endsWith(","),D=y.match(/:\s*\{[^}]*\},\s*$/),I;D||w?I=`${y}
235
- ${c}
236
- ${x}`:I=y.trimEnd()+`
237
- `+c+`
238
- `+x,await to(s,I)}catch(o){throw new Error(`Failed to register API endpoints: ${o}`)}};var ft=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(t,i)=>{try{let r=process.cwd();i.store&&!["persist","no-persist"].includes(i.store)&&(R("Invalid --store option. Use: persist or no-persist"),process.exit(1)),i.service&&!["axios","fetch"].includes(i.service)&&(R("Invalid --service option. Use: axios or fetch"),process.exit(1)),i.skipStore&&i.store&&(R("Cannot use --skip-store and --store together"),process.exit(1)),i.skipService&&i.service&&(R("Cannot use --skip-service and --service together"),process.exit(1)),f(O.cyan(`
239
- \u{1F3AF} Feature Generator
240
- `)),v.start("Detecting project setup...");let s=await re(r);v.succeed("Project setup detected"),f(O.dim(` Redux: ${s.hasRedux?"\u2713":"\u2717"}`)),f(O.dim(` HTTP Client: ${s.httpClient}`)),f(O.dim(` i18n: ${s.hasI18n?"\u2713":"\u2717"}
241
- `));let o=await at(t,s.hasRedux,s.httpClient,i.skipStore,i.store,i.skipService,i.service),n=i.path||De.join("src","features"),c=De.join(r,n,o.featureName);await ct(r,o.featureName,n)&&(R(`Feature '${o.featureName}' already exists at ${n}!`),process.exit(1)),v.start("Generating feature files..."),await lt({featureName:o.featureName,featurePath:c,createStore:o.createStore,persistStore:o.persistStore,createService:o.createService,httpClient:o.selectedHttpClient}),v.succeed("Feature files generated"),o.createService&&(v.start("Registering API endpoints..."),await ge({serviceName:o.featureName,projectPath:r}),v.succeed("API endpoints registered")),o.createStore&&s.hasRedux&&(v.start("Registering feature in rootReducer..."),await dt(r,o.featureName,o.persistStore,n),v.succeed("Feature registered in rootReducer"));let m=De.join(n,o.featureName);f(O.green(`
242
- \u2728 Feature '${o.featureName}' created successfully!
243
- `)),f(O.dim("Generated files:")),f(O.dim(` \u{1F4C2} ${m}/`)),f(O.dim(" \u251C\u2500\u2500 components/")),f(O.dim(" \u251C\u2500\u2500 hooks/")),f(O.dim(" \u251C\u2500\u2500 types/")),o.createStore&&f(O.dim(" \u251C\u2500\u2500 store/")),o.createService&&f(O.dim(" \u251C\u2500\u2500 services/")),f(O.dim(` \u2514\u2500\u2500 index.ts
244
- `)),f(O.cyan("Next steps:"));let h=n.replace(/^src\//,"@/");f(O.dim(` 1. Import and use the feature: import { ${o.featureName} } from '${h}/${o.featureName}'`)),o.createStore&&f(O.dim(` 2. Customize your Redux slice in: ${m}/store/`)),o.createService&&f(O.dim(` 3. Add API methods in: ${m}/services/${o.featureName}.service.ts`)),f("")}catch(r){v.fail("Feature generation failed"),R(`${r}`),process.exit(1)}})};import k from"picocolors";import B from"node:path";import{existsSync as uo}from"node:fs";import{mkdir as fo}from"node:fs/promises";import oo from"enquirer";var{prompt:ro}=oo,gt=async(e,t,i)=>{let r=[];e||r.push({type:"input",name:"sliceName",message:"What is the slice name?",initial:"my-slice",validate:o=>/^[a-z0-9-]+$/.test(o)?!0:"Slice name must be lowercase and contain only alphanumeric characters and hyphens."}),t===void 0&&i===void 0&&r.push({type:"confirm",name:"persistSlice",message:"Enable persistence for this slice?",initial:!1});let s=r.length>0?await ro(r):{};return{sliceName:e||s.sliceName,persistSlice:t===!0?!0:i===!1?!1:s.persistSlice||!1}};import{writeFile as ce,mkdir as no}from"node:fs/promises";import le from"node:path";var xt=async e=>{let{sliceName:t,slicePath:i,persistSlice:r}=e;await no(i,{recursive:!0});let s=V(t),o=L(t);await so(t,i,s),await ao(t,i,s,o),await co(t,i,s,o),r&&await lo(t,i,s,o),await po(t,i,r)},so=async(e,t,i)=>{let r=`export interface ${i}State {
245
- loading: boolean;
246
- error: string | null;
247
- // Add your state properties here
255
+ getById: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
256
+ create: \`\${API_PREFIX}/${t}\`,
257
+ update: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
258
+ delete: (id: string) => \`\${API_PREFIX}/${t}/\${id}\`,
259
+ },`};var tt=async e=>{let{name:o,outputPath:t,httpClient:r}=e,n=k(o),i=N(o);await Si(Ci.join(t,`${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=e=>{let{componentName:o,routePath:t,hasI18n:r}=e;return r?`import { generateSEOMetadata } from '@/lib/config/seo';
260
+ import { SupportedLocale } from '@/types/i18n';
261
+ import { Metadata } from 'next';
262
+ import { getTranslations, setRequestLocale } from 'next-intl/server';
263
+
264
+ type Props = {
265
+ params: Promise<{ locale: string }>;
266
+ };
267
+
268
+ export async function generateMetadata(props: Props): Promise<Metadata> {
269
+ const locale = (await props.params).locale as SupportedLocale;
270
+ const t = await getTranslations({ locale, namespace: '${o}' });
271
+
272
+ return generateSEOMetadata({
273
+ title: t('title'),
274
+ description: t('description'),
275
+ path: '${t}',
276
+ });
248
277
  }
249
- `;await ce(le.join(t,`${e}.types.ts`),r)},ao=async(e,t,i,r)=>{let s=`import { createSlice, PayloadAction } from '@reduxjs/toolkit';
250
- import { ${i}State } from './${e}.types';
251
278
 
252
- const initialState: ${i}State = {
253
- loading: false,
254
- error: null,
255
- // Add your initial state here
279
+ export default async function ${o}Page(props: Props) {
280
+ const locale = (await props.params).locale as SupportedLocale;
281
+ setRequestLocale(locale);
282
+
283
+ const t = await getTranslations('${o}');
284
+
285
+ return (
286
+ <div>
287
+ <h1>{t('title')}</h1>
288
+ </div>
289
+ );
290
+ }
291
+ `:`import { Metadata } from 'next';
292
+
293
+ export const metadata: Metadata = {
294
+ title: '${o}',
295
+ description: '${o} page',
256
296
  };
257
297
 
258
- export const ${r}Slice = createSlice({
259
- name: '${r}',
260
- initialState,
261
- reducers: {
262
- setLoading: (state, action: PayloadAction<boolean>) => {
263
- state.loading = action.payload;
264
- },
265
- setError: (state, action: PayloadAction<string | null>) => {
266
- state.error = action.payload;
267
- },
268
- resetState: (state) => {
269
- state.loading = false;
270
- state.error = null;
271
- },
272
- },
273
- });
298
+ export default function ${o}Page() {
299
+ return (
300
+ <div>
301
+ <h1>${o}</h1>
302
+ </div>
303
+ );
304
+ }
305
+ `},go=e=>{let{componentName:o,paramName:t,routePath:r,hasI18n:n}=e;return n?`import { generateSEOMetadata } from '@/lib/config/seo';
306
+ import { SupportedLocale } from '@/types/i18n';
307
+ import { Metadata } from 'next';
308
+ import { getTranslations, setRequestLocale } from 'next-intl/server';
274
309
 
275
- export const { setLoading, setError, resetState } = ${r}Slice.actions;
310
+ type Props = {
311
+ params: Promise<{ locale: string; ${t}: string }>;
312
+ };
276
313
 
277
- export const ${r}Reducer = ${r}Slice.reducer;
278
- `;await ce(le.join(t,`${e}.slice.ts`),s)},co=async(e,t,i,r)=>{let s=`import { RootState } from '@/store/rootReducer';
314
+ export async function generateMetadata(props: Props): Promise<Metadata> {
315
+ const { locale, ${t} } = await props.params;
316
+ const t = await getTranslations({ locale: locale as SupportedLocale, namespace: '${o}' });
279
317
 
280
- export const select${i}State = (state: RootState) => state.${r};
281
- export { setLoading, setError, resetState } from './${e}.slice';
282
- `;await ce(le.join(t,`${e}.selectors.ts`),s)},lo=async(e,t,i,r)=>{let s=`import { PersistConfig } from 'redux-persist';
283
- import storage from 'redux-persist/lib/storage';
284
- import { ${i}State } from './${e}.types';
318
+ return generateSEOMetadata({
319
+ title: t('title'),
320
+ description: t('description'),
321
+ path: '${r}',
322
+ });
323
+ }
285
324
 
286
- export const ${r}PersistConfig: PersistConfig<${i}State> = {
287
- key: '${r}',
288
- storage,
289
- // whitelist: ['someField'], // Specify which fields to persist
325
+ export default async function ${o}Page(props: Props) {
326
+ const { locale, ${t} } = await props.params;
327
+ setRequestLocale(locale);
328
+
329
+ const t = await getTranslations('${o}');
330
+
331
+ return (
332
+ <div>
333
+ <h1>{t('title')}</h1>
334
+ <p>${o}: {${t}}</p>
335
+ </div>
336
+ );
337
+ }
338
+ `:`import { Metadata } from 'next';
339
+
340
+ export const metadata: Metadata = {
341
+ title: '${o}',
342
+ description: '${o} page',
290
343
  };
291
- `;await ce(le.join(t,"persist.ts"),s)},po=async(e,t,i)=>{let r=`export * from './${e}.slice';
292
- export * from './${e}.selectors';
293
- export * from './${e}.types';${i?`
294
- export * from './persist';`:""}
295
- `;await ce(le.join(t,"index.ts"),r)};import{access as mo}from"node:fs/promises";import ht from"node:path";var yt=async(e,t,i=ht.join("src","store","slices"))=>{let r=ht.join(e,i,t);try{return await mo(r),!0}catch{return!1}};var St=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").action(async(t,i)=>{try{let r=process.cwd();i.persist&&i.noPersist===!0&&(R("Cannot use --persist and --no-persist together"),process.exit(1)),f(k.cyan(`
296
- \u{1F527} Slice Generator
297
- `)),v.start("Detecting project setup...");let s=await re(r);v.succeed("Project setup detected"),s.hasRedux||(v.fail("Redux is not setup in this project"),R("Please install @reduxjs/toolkit and react-redux first"),f(k.dim(`
298
- Run: npm install @reduxjs/toolkit react-redux
299
- `)),process.exit(1)),f(k.dim(` Redux: \u2713
300
- `));let o=await gt(t,i.persist,i.noPersist===!0?!1:void 0),n,c,p;if(i.path){let w=i.path.replace(/^src\//,"");w.startsWith("features/")?(c=w.split("/")[1],n=B.join("src","features",c,"store"),p=B.join(r,n,o.sliceName)):(n=B.join("src",w),c=w.split("/")[0],p=B.join(r,n,o.sliceName))}else c=o.sliceName,n=B.join("src","features",c,"store"),p=B.join(r,n,o.sliceName);let m=B.join(r,n);uo(m)||await fo(m,{recursive:!0}),await yt(r,o.sliceName,n)&&(R(`Slice '${o.sliceName}' already exists at ${n}!`),process.exit(1)),v.start("Generating slice files..."),await xt({sliceName:o.sliceName,slicePath:p,persistSlice:o.persistSlice}),v.succeed("Slice files generated"),v.start("Registering slice in rootReducer..."),await ut(r,o.sliceName,o.persistSlice,n),v.succeed("Slice registered in rootReducer");let y=B.join(n,o.sliceName);f(k.green(`
301
- \u2728 Slice '${o.sliceName}' created successfully!
302
- `)),f(k.dim("Generated files:")),f(k.dim(` \u{1F4C2} ${y}/`)),f(k.dim(` \u251C\u2500\u2500 ${o.sliceName}.slice.ts`)),f(k.dim(` \u251C\u2500\u2500 ${o.sliceName}.selectors.ts`)),o.persistSlice&&f(k.dim(" \u251C\u2500\u2500 persist.ts")),f(k.dim(` \u251C\u2500\u2500 ${o.sliceName}.types.ts`)),f(k.dim(` \u2514\u2500\u2500 index.ts
303
- `)),f(k.cyan("Next steps:"));let x=n.replace(/^src\//,"@/");f(k.dim(` 1. Import actions: import { setLoading, setError } from '${x}/${o.sliceName}'`)),f(k.dim(" 2. Use in component: dispatch(setLoading(true))")),f("")}catch(r){v.fail("Slice generation failed"),R(`${r}`),process.exit(1)}})};import J from"picocolors";import ee from"node:path";import{existsSync as Po}from"node:fs";import{mkdir as vo}from"node:fs/promises";import Pt from"enquirer";var vt=async(e,t,i,r)=>{let s=e||(await Pt.prompt({type:"input",name:"serviceName",message:"Service name (kebab-case):",validate:n=>n?/^[a-z0-9-]+$/.test(n)?!0:"Service name must be lowercase with hyphens only":"Service name is required"})).serviceName,o;return t!==void 0?o="axios":i!==void 0?o="fetch":r==="axios"?o="axios":r==="fetch"?o="fetch":r==="both"?o=(await Pt.prompt({type:"select",name:"httpClient",message:"Choose HTTP client:",choices:["axios","fetch"]})).httpClient:o="axios",{serviceName:s,httpClient:o}};import{writeFile as go}from"node:fs/promises";import xo from"node:path";var wt=async e=>{await ho(e)},ho=async e=>{let{serviceName:t,servicePath:i,httpClient:r}=e,s=L(t),o;r==="axios"?o=`import { AppApis } from '@/lib/config';
304
- import { axiosClient } from '@/lib/utils/http';
305
- import { ResultAsync } from '@/types';
306
344
 
307
- export const ${s}Service = {
308
- getAll: (): ResultAsync<string> => {
309
- return axiosClient.get<string>(AppApis.${s}.getAll);
310
- },
345
+ type Props = {
346
+ params: Promise<{ ${t}: string }>;
311
347
  };
312
- `:o=`import { AppApis } from '@/lib/config';
313
- import { fetchClient } from '@/lib/utils/http';
314
- import { ResultAsync } from '@/types';
315
348
 
316
- export const ${s}Service = {
317
- getAll: (): ResultAsync<string> => {
318
- return fetchClient.get<string>(AppApis.${s}.getAll);
349
+ export default async function ${o}Page(props: Props) {
350
+ const { ${t} } = await props.params;
351
+
352
+ return (
353
+ <div>
354
+ <h1>${o}</h1>
355
+ <p>${o}: {${t}}</p>
356
+ </div>
357
+ );
358
+ }
359
+ `},ho=e=>`export default function ${e.componentName}Loading() {
360
+ return (
361
+ <div className="flex h-full items-center justify-center">
362
+ <p>Loading...</p>
363
+ </div>
364
+ );
365
+ }
366
+ `,xo=e=>`'use client';
367
+
368
+ export default function ${e.componentName}Error({
369
+ error,
370
+ reset,
371
+ }: {
372
+ error: Error & { digest?: string };
373
+ reset: () => void;
374
+ }) {
375
+ return (
376
+ <div className="flex h-full flex-col items-center justify-center gap-4">
377
+ <h2>Something went wrong!</h2>
378
+ <p>{error.message}</p>
379
+ <button onClick={() => reset()}>Try again</button>
380
+ </div>
381
+ );
382
+ }
383
+ `;var rt=async e=>{let{name:o,projectPath:t,hasI18n:r,dynamic:n,withLoading:i=!1,withError:s=!1}=e,c=N(o),m=`/${o}`,f=r?"src/app/[locale]":"src/app",x;n?x=ge.join(t,f,o,`[${n}]`):x=ge.join(t,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=e=>{let{componentName:o,isClient:t,hasI18n:r}=e,n=e.translationNamespace||o,i=[];return(t||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(`
384
+ `)},yo=e=>`export { ${e.componentName} } from './${e.componentName}';
385
+ `;w();var st=async e=>{let{name:o,projectPath:t,isClient:r,hasI18n:n,featurePath:i}=e,s=N(o);i?await Ti(s,t,i,r,n):await Ei(s,o,t,r,n)},Ti=async(e,o,t,r,n)=>{let i=ie.join(o,t,"components");await Po(i,{recursive:!0}),await nt(ie.join(i,`${e}.tsx`),it({componentName:e,isClient:r,hasI18n:n}))},Ei=async(e,o,t,r,n)=>{let i=ie.join(t,"src","components","common",e);await Po(i,{recursive:!0}),await nt(ie.join(i,`${e}.tsx`),it({componentName:e,isClient:r,hasI18n:n})),await nt(ie.join(i,"index.ts"),yo({componentName:e}));let s=ie.join(t,"src","components","common","index.ts");await Ii(s,`export { ${e} } from './${e}';
386
+ `);let c=ie.join(t,"src","components","index.ts");await Ni(c)},Ii=async(e,o)=>{let t="";l(e)&&(t=await d(e)),t.includes(o.trim())||(t+=o,await u(e,t))},Ni=async e=>{let o="";l(e)&&(o=await d(e));let t=`export * from './common';
387
+ `;o.includes(t.trim())||(o+=t,await u(e,o))};w();import{readFile as Ri,writeFile as $i,copyFile as Ai}from"node:fs/promises";import he from"node:path";var at=async e=>{let{code:o,name:t,country:r,flag:n,projectPath:i,copyTranslations:s}=e;await bi(i,o,s),await Oi(i,o),await ki(i,o,t,r,n)},bi=async(e,o,t)=>{let r=he.join(e,"src","i18n","translations"),n=he.join(r,"en.json"),i=he.join(r,`${o}.json`);if(t)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)+`
388
+ `)}},wo=e=>{let o={};for(let[t,r]of Object.entries(e))typeof r=="object"&&r!==null?o[t]=wo(r):o[t]="";return o},Oi=async(e,o)=>{let t=he.join(e,"src","types","i18n.ts");if(!l(t))return;let r=await d(t),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(t,r)}},ki=async(e,o,t,r,n)=>{let i=he.join(e,"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=` {
389
+ name: '${t}',
390
+ locale: '${o}',
391
+ flag: '${n}',
392
+ country: '${r}',
319
393
  },
320
- };
321
- `;let n=`${t}.service.ts`;await go(xo.join(i,n),o)};import{existsSync as yo}from"node:fs";import So from"node:path";var Ct=async(e,t,i)=>{let r=So.join(e,i,`${t}.service.ts`);return yo(r)};var Tt=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").action(async(t,i)=>{try{let r=process.cwd();i.axios&&i.fetch&&(R("Cannot use --axios and --fetch together"),process.exit(1)),f(J.cyan(`
394
+ `;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=e=>{let{hookName:o,isClient:t}=e,r=[];return t&&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(`
395
+ `)};var pt=async e=>{let{name:o,projectPath:t,isClient:r,featurePath:n}=e,s=`use${N(o)}`,c;n?c=ct.join(t,n,"hooks"):c=ct.join(t,"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=(e,o)=>{let t=/import\s+.*\s+from\s+['"].*['"];?\n/g,r=e.match(t);if(r&&r.length>0){let n=r[r.length-1],i=e.lastIndexOf(n);return e.slice(0,i+n.length)+o+`
396
+ `+e.slice(i+n.length)}return o+`
397
+ `+e},lt=(e,o,t)=>{let r=/combineReducers\(\{([^}]*)\}\)/s,n=e.match(r);if(!n)throw new Error("Could not find combineReducers in rootReducer.ts");let i=n[1],s=`
398
+ ${o}: ${t},`,c=i.trimEnd()+s;return e.replace(r,`combineReducers({${c}
399
+ })`)},xe=(e,o)=>{let t=e.lastIndexOf("} as const;");if(t===-1)throw new Error("Could not find closing brace of AppApis object");let r=e.substring(0,t),n=e.substring(t);return r.trimEnd()+`
400
+ `+o+`
401
+ `+n};var ye=async e=>{let{projectPath:o,name:t,persist:r,importPath:n}=e,i=Li.join(o,"src","store","rootReducer.ts");try{let s=await Fi(i,"utf-8"),c=k(t),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 '${t}' in rootReducer: ${s}`,{cause:s})}};import{readFile as Hi,writeFile as Gi}from"node:fs/promises";import Mi from"node:path";var Pe=async e=>{let{serviceName:o,projectPath:t}=e,r=k(o),n=Mi.join(t,"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}: {
402
+ base: \`\${API_PREFIX}/${o}\`,
403
+ getAll: \`\${API_PREFIX}/${o}\`,
404
+ },`;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";w();var dt=async(e,o,t)=>{let r=Ji.join(e,"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}: '${t}',
405
+ `;n=n.slice(0,s)+c+n.slice(s),await Xi(r,n)};w();import{readFile as Yi,writeFile as zi}from"node:fs/promises";import Wi from"node:path";var ut=async(e,o)=>{let t=Wi.join(e,"src","i18n","translations","en.json");if(!l(t))return;let r=await Yi(t,"utf-8"),n=JSON.parse(r);n[o]||(n[o]={title:o,description:`${o} page description`},await zi(t,JSON.stringify(n,null,2)+`
406
+ `))};W();var ft=()=>[{name:"Project setup detected",spinnerText:"Detecting project setup...",execute:async e=>{e.detection=await _(e.projectPath)}},{name:"Feature files generated",spinnerText:"Generating feature files...",execute:async e=>{await et({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 Pe({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 ye({projectPath:e.projectPath,name:e.featureName,persist:e.persistStore,importPath:Bi.join(e.basePath,e.featureName,"store")})}}];import Vi from"node:path";var gt=()=>[{name:"Slice files generated",spinnerText:"Generating slice files...",execute:async e=>{await ue({name:e.sliceName,outputPath:e.slicePath,persist:e.persistSlice})}},{name:"Slice registered in rootReducer",spinnerText:"Registering slice in rootReducer...",execute:async e=>{await ye({projectPath:e.projectPath,name:e.sliceName,persist:e.persistSlice,importPath:Vi.join(e.basePath,e.sliceName)})}}];var ht=()=>[{name:"Service files generated",spinnerText:"Generating service files...",execute:async e=>{await fe({name:e.serviceName,outputPath:e.servicePath,httpClient:e.httpClient})}},{name:"API endpoints registered",spinnerText:"Registering API endpoints...",execute:async e=>{await Pe({serviceName:e.serviceName,projectPath:e.projectPath})}}];var Co=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(o,t)=>{try{let r=process.cwd();qi(t),p($.cyan(`
407
+ \u{1F3AF} Feature Generator
408
+ `));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"}
409
+ `));let c=await qt(o,s.hasRedux,s.httpClient,t.skipStore,t.store,t.skipService,t.service),m=t.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=e=>{e.store&&!["persist","no-persist"].includes(e.store)&&(C("Invalid --store option. Use: persist or no-persist"),process.exit(1)),e.service&&!["axios","fetch"].includes(e.service)&&(C("Invalid --service option. Use: axios or fetch"),process.exit(1)),e.skipStore&&e.store&&(C("Cannot use --skip-store and --store together"),process.exit(1)),e.skipService&&e.service&&(C("Cannot use --skip-service and --service together"),process.exit(1))},Ki=(e,o)=>{let t=xt.join(o,e.featureName);p($.green(`
410
+ \u2728 Feature '${e.featureName}' created successfully!
411
+ `)),p($.dim("Generated files:")),p($.dim(` \u{1F4C2} ${t}/`)),p($.dim(" \u251C\u2500\u2500 components/")),p($.dim(" \u251C\u2500\u2500 hooks/")),p($.dim(" \u251C\u2500\u2500 types/")),e.createStore&&p($.dim(" \u251C\u2500\u2500 store/")),e.createService&&p($.dim(" \u251C\u2500\u2500 services/")),p($.dim(` \u2514\u2500\u2500 index.ts
412
+ `)),p($.cyan("Next steps:"));let r=o.replace(/^src\//,"@/");p($.dim(` 1. Import and use the feature: import { ${e.featureName} } from '${r}/${e.featureName}'`)),e.createStore&&p($.dim(` 2. Customize your Redux slice in: ${t}/store/`)),e.createService&&p($.dim(` 3. Add API methods in: ${t}/services/${e.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(e,o,t)=>{let r=[];e||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&&t===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:e||n.sliceName,persistSlice:o===!0?!0:t===!1?!1:n.persistSlice||!1}};W();var To=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").action(async(o,t)=>{try{let r=process.cwd();t.persist&&t.noPersist===!0&&(C("Cannot use --persist and --no-persist together"),process.exit(1)),p(j.cyan(`
413
+ \u{1F527} Slice Generator
414
+ `)),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(`
415
+ Run: npm install @reduxjs/toolkit react-redux
416
+ `)),process.exit(1)),p(j.dim(` Redux: \u2713
417
+ `));let i=await vo(o,t.persist,t.noPersist===!0?!1:void 0),{basePath:s,slicePath:c}=on(r,i.sliceName,t.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=(e,o,t)=>{let r;if(t){let n=t.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(e,r,o)}},rn=(e,o)=>{let t=pe.join(o,e.sliceName);p(j.green(`
418
+ \u2728 Slice '${e.sliceName}' created successfully!
419
+ `)),p(j.dim("Generated files:")),p(j.dim(` \u{1F4C2} ${t}/`)),p(j.dim(` \u251C\u2500\u2500 ${e.sliceName}.slice.ts`)),p(j.dim(` \u251C\u2500\u2500 ${e.sliceName}.selectors.ts`)),e.persistSlice&&p(j.dim(" \u251C\u2500\u2500 persist.ts")),p(j.dim(` \u251C\u2500\u2500 ${e.sliceName}.types.ts`)),p(j.dim(` \u2514\u2500\u2500 index.ts
420
+ `)),p(j.cyan("Next steps:"));let r=o.replace(/^src\//,"@/");p(j.dim(` 1. Import actions: import { setLoading, setError } from '${r}/${e.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(e,o,t,r)=>{let n=e||(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":t!==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(e,o)=>{let t=k(o),r=an.join(e,"src","lib","config","app-apis.ts");try{let n=await nn(r,"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=uo({camelName:t,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=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(o,t)=>{try{let r=process.cwd();t.axios&&t.fetch&&(C("Cannot use --axios and --fetch together"),process.exit(1)),p(H.cyan(`
322
421
  \u{1F527} Service Generator
323
- `)),v.start("Detecting project setup...");let s=await re(r);v.succeed("Project setup detected"),s.httpClient==="none"&&(v.fail("No HTTP client is setup in this project"),R("Please setup either AxiosClient or FetchClient first"),f(J.dim(`
422
+ `)),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(`
324
423
  Check: lib/utils/http/axios-client or lib/utils/http/fetch-client
325
- `)),process.exit(1));let o=[];(s.httpClient==="axios"||s.httpClient==="both")&&o.push("Axios \u2713"),(s.httpClient==="fetch"||s.httpClient==="both")&&o.push("Fetch \u2713"),f(J.dim(` HTTP Clients: ${o.join(", ")}
326
- `));let n=await vt(t,i.axios,i.fetch,s.httpClient),c,p,m;if(i.path){let w=i.path.replace(/^src\//,"");w.startsWith("features/")?(p=w.split("/")[1],c=ee.join("src","features",p,"services"),m=ee.join(r,c)):(c=ee.join("src",w),p=w.split("/")[0],m=ee.join(r,c))}else p=n.serviceName,c=ee.join("src","features",p,"services"),m=ee.join(r,c);Po(m)||await vo(m,{recursive:!0}),await Ct(r,n.serviceName,c)&&(R(`Service '${n.serviceName}' already exists at ${c}!`),process.exit(1)),v.start("Generating service files..."),await wt({serviceName:n.serviceName,servicePath:m,httpClient:n.httpClient}),v.succeed("Service files generated"),v.start("Registering API endpoints..."),await ge({serviceName:n.serviceName,projectPath:r}),v.succeed("API endpoints registered");let y=ee.join(c,`${n.serviceName}.service.ts`);f(J.green(`
327
- \u2728 Service '${n.serviceName}' created successfully!
328
- `)),f(J.dim("Generated files:")),f(J.dim(` \u{1F4C4} ${y}
329
- `)),f(J.cyan("Next steps:"));let x=c.replace(/^src\//,"@/");f(J.dim(` 1. Import service: import { ${n.serviceName}Service } from '${x}/${n.serviceName}.service'`)),f(J.dim(` 2. Use in component: const data = await ${n.serviceName}Service.getAll()`)),f("")}catch(r){v.fail("Service generation failed"),R(`${r}`),process.exit(1)}})};import we from"picocolors";import Do from"enquirer";T();import Co from"node:path";import To from"picocolors";T();N();import pe from"node:path";T();N();import Et from"node:path";var xe=async e=>{let t=[Et.join(e,a.ROOT_LAYOUT),Et.join(e,"src/app/[locale]/layout.tsx")];for(let i of t)if(l(i)&&(await d(i)).includes("<body"))return i;for(let i of t)if(l(i))return i;return""};var It=async e=>{let t=pe.join(e,a.THEME_PROVIDER),i=pe.join(e,a.GLOBALS_CSS),r=pe.join(e,"package.json");if(l(t))return{isSetup:!0,reason:"CustomThemeProvider.tsx exists"};if(l(r)){let s=JSON.parse(await d(r));if(s.dependencies&&s.dependencies["next-themes"]||s.devDependencies&&s.devDependencies["next-themes"])return{isSetup:!0,reason:"next-themes is installed"}}return l(i)&&(await d(i)).includes("@custom-variant dark")?{isSetup:!0,reason:"Dark theme CSS found in globals.css"}:{isSetup:!1,reason:""}},Rt=async e=>{let t=pe.join(e,a.GLOBALS_CSS),i=pe.join(e,a.PROVIDERS_INDEX),r=await xe(e);if(!l(t)||!r||!l(i))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};T();N();import Nt from"node:path";import wo from"degit";var At=async(e,t)=>{t.text="Fetching assets from starter repo...",await wo("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Ot=async(e,t)=>{let i=Nt.join(e,a.THEME_PROVIDER),r=Nt.join(t,"src/providers/CustomThemeProvider.tsx");await b(r,i)};T();N();import he from"node:path";var $t=async e=>{let t=he.join(e,a.PROVIDERS_INDEX),i=await d(t);i.includes("CustomThemeProvider")||(i+=`export * from './CustomThemeProvider';
330
- `,await u(t,i))},_t=async e=>{let t=he.join(e,"src/providers/RootProvider.tsx");if(l(t)){let i=await d(t),r="'use client';",s=i.includes(r);if(s&&(i=i.replace(r,"").trim()),i.includes("CustomThemeProvider")||(i=i.replace(/import \{ StoreProvider \} from '@\/providers';\n/,`import { StoreProvider, CustomThemeProvider } from '@/providers';
331
- `),i.includes("CustomThemeProvider")||(i.includes("from '@/providers'")?i=i.replace(/\} from '@\/providers'/,", CustomThemeProvider } from '@/providers'"):i=`import { CustomThemeProvider } from '@/providers';
332
- `+i)),s&&(i=r+`
333
- `+i),!i.includes("<CustomThemeProvider>")){if(i.includes("<StoreProvider>"))i=i.replace(/<StoreProvider>/,`<StoreProvider>
334
- <CustomThemeProvider>`),i=i.replace(/<\/StoreProvider>/,`</CustomThemeProvider>
335
- </StoreProvider>`);else{let o=i.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(o){let n=o[1];i=i.replace(o[0],`return (
424
+ `)),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(", ")}
425
+ `));let s=await Io(o,t.axios,t.fetch,n.httpClient),{basePath:c,servicePath:m}=mn(r,s.serviceName,t.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)),t.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,!!t.crud)}catch(r){g.fail("Service generation failed"),C(`${r}`),process.exit(1)}})},mn=(e,o,t)=>{let r;if(t){let n=t.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(e,r)}},ln=(e,o,t=!1)=>{let r=we.join(o,`${e.serviceName}.service.ts`);p(H.green(`
426
+ \u2728 ${t?"CRUD ":""}Service '${e.serviceName}' created successfully!
427
+ `)),p(H.dim("Generated files:")),p(H.dim(` \u{1F4C4} ${r}
428
+ `)),p(H.cyan("Next steps:"));let n=o.replace(/^src\//,"@/");p(H.dim(` 1. Import service: import { ${e.serviceName}Service } from '${n}/${e.serviceName}.service'`)),t?(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 ${e.serviceName}Service.getAll()`)),p("")};import He from"picocolors";import Nn from"enquirer";w();import un from"node:path";import fn from"picocolors";w();T();import Se from"node:path";w();T();import $o from"node:path";var ke=async e=>{let o=[$o.join(e,a.ROOT_LAYOUT),$o.join(e,"src/app/[locale]/layout.tsx")];for(let t of o)if(l(t)&&(await d(t)).includes("<body"))return t;for(let t of o)if(l(t))return t;return""};var Ao=async e=>{let o=Se.join(e,a.THEME_PROVIDER),t=Se.join(e,a.GLOBALS_CSS),r=Se.join(e,"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(t)&&(await d(t)).includes("@custom-variant dark")?{isSetup:!0,reason:"Dark theme CSS found in globals.css"}:{isSetup:!1,reason:""}},bo=async e=>{let o=Se.join(e,a.GLOBALS_CSS),t=Se.join(e,a.PROVIDERS_INDEX),r=await ke(e);if(!l(o)||!r||!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 r};w();T();import Oo from"node:path";import dn from"degit";var ko=async(e,o)=>{o.text="Fetching assets from starter repo...",await dn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},_o=async(e,o)=>{let t=Oo.join(e,a.THEME_PROVIDER),r=Oo.join(o,"src/providers/CustomThemeProvider.tsx");await O(r,t)};w();T();import _e from"node:path";var jo=async e=>{let o=_e.join(e,a.PROVIDERS_INDEX),t=await d(o);t.includes("CustomThemeProvider")||(t+=`export * from './CustomThemeProvider';
429
+ `,await u(o,t))},Fo=async e=>{let o=_e.join(e,"src/providers/RootProvider.tsx");if(l(o)){let t=await d(o),r="'use client';",n=t.includes(r);if(n&&(t=t.replace(r,"").trim()),t.includes("CustomThemeProvider")||(t=t.replace(/import \{ StoreProvider \} from '@\/providers';\n/,`import { StoreProvider, CustomThemeProvider } from '@/providers';
430
+ `),t.includes("CustomThemeProvider")||(t.includes("from '@/providers'")?t=t.replace(/\} from '@\/providers'/,", CustomThemeProvider } from '@/providers'"):t=`import { CustomThemeProvider } from '@/providers';
431
+ `+t)),n&&(t=r+`
432
+ `+t),!t.includes("<CustomThemeProvider>")){if(t.includes("<StoreProvider>"))t=t.replace(/<StoreProvider>/,`<StoreProvider>
433
+ <CustomThemeProvider>`),t=t.replace(/<\/StoreProvider>/,`</CustomThemeProvider>
434
+ </StoreProvider>`);else{let i=t.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(i){let s=i[1];t=t.replace(i[0],`return (
336
435
  <CustomThemeProvider>
337
- ${n}
436
+ ${s}
338
437
  </CustomThemeProvider>
339
- );`)}}await u(t,i)}}},bt=async(e,t)=>{let i=he.join(e,a.GLOBALS_CSS),r=he.join(t,"src/styles/globals.css"),s="";if(l(r)){let n=await d(r),c=n.match(/@custom-variant dark \(.*?\);/),p=n.match(/@theme \{[\s\S]*?\}/);c&&(s+=`
438
+ );`)}}await u(o,t)}}},Do=async(e,o)=>{let t=_e.join(e,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+=`
340
439
  ${c[0]}
341
- `),p&&(s+=`
342
- ${p[0]}
343
- `)}s||(s=`
440
+ `),m&&(n+=`
441
+ ${m[0]}
442
+ `)}n||(n=`
344
443
  @custom-variant dark (&:where(.dark, .dark *));
345
444
 
346
445
  @theme {
347
446
  --color-dark: #202938;
348
447
  --color-light: #f5f5f5;
349
448
  }
350
- `);let o=await d(i);if(!o.includes("@custom-variant dark")){if(o.includes("@import")){let n=o.lastIndexOf("@import"),c=o.indexOf(`
351
- `,n);o=o.slice(0,c+1)+s+o.slice(c+1)}else o=s+o;await u(i,o)}},Ft=async e=>{let t=await d(e);t.includes("dark:bg-dark")||(t=t.replace(/className="([^"]*)"/,'className="$1 bg-light dark:bg-dark"'),await u(e,t))};var Le=async e=>{let t=$("Setting up Dark Theme..."),i=Co.join(e,".next-maker-temp");try{let{isSetup:r,reason:s}=await It(e);if(r){t.fail(`Dark Theme is already set up (${s}).`);return}let o=await Rt(e);await At(i,t),await Ot(e,i),await $t(e),await _t(e),await bt(e,i),await Ft(o),t.text="Installing next-themes...",await M(e,"next-themes"),t.text="Formatting code...";let n=await G(e);await H(e,n,"format"),t.succeed(To.green("Dark Theme setup successfully!"))}catch(r){throw t.fail("Failed to setup Dark Theme."),r}finally{await S(i)}};T();import Io from"node:path";import Ro from"picocolors";T();N();import Me from"node:path";var jt=async e=>{let t=Me.join(e,a.STORE),i=Me.join(e,"package.json");if(l(t))return{isSetup:!0,reason:"src/store directory exists"};if(l(i)){let r=JSON.parse(await d(i));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:""}},kt=async e=>{let t=Me.join(e,a.PROVIDERS_INDEX);if(!await xe(e)||!l(t))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx (or src/app/[locale]/layout.tsx) and src/providers/index.ts exist.")};T();N();import te from"node:path";import Eo from"degit";import Dt from"node:fs/promises";var Lt=async(e,t)=>{t.text="Fetching assets from starter repo...",await Eo("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Mt=async(e,t)=>{let i=te.join(t,"src/providers/StoreProvider.tsx"),r=te.join(e,a.STORE_PROVIDER);await b(i,r);let s=te.join(t,"src/store"),o=te.join(e,a.STORE);await Dt.cp(s,o,{recursive:!0})},Ht=async(e,t)=>{let i=te.join(t,"src/features/counter"),r=te.join(e,a.COUNTER_FEATURE);await Dt.cp(i,r,{recursive:!0});let s=te.join(r,"components/Counter.tsx");if(await l(s)){let o=await d(s);o=o.replace(/import \{ useTranslations \} from 'next-intl';\n?/,""),o=o.replace(/const t = useTranslations\('Count'\);\n?/,""),o=o.replace(/\{t\('currentCount', \{ count: value \}\)\}/g,"Current Count: {value}"),o=o.replace(/\{t\('increment'\)\}/g,"Increment"),o=o.replace(/\{t\('decrement'\)\}/g,"Decrement"),o=o.replace(/\{t\('reset'\)\}/g,"Reset"),await u(s,o)}};T();N();import ye from"node:path";var Gt=async e=>{let t=ye.join(e,a.PROVIDERS_INDEX),i=await d(t);i.includes("StoreProvider")||(i+=`export * from './StoreProvider';
352
- `,await u(t,i))},Ut=async e=>{let t=ye.join(e,"src/providers/RootProvider.tsx");if(l(t)){let i=await d(t),r="'use client';",s=i.includes(r);if(s&&(i=i.replace(r,"").trim()),i.includes("StoreProvider")||(i=i.replace(/import \{ (.*?) \} from '@\/providers';/,"import { $1, StoreProvider } from '@/providers';"),i.includes("StoreProvider")||(i.includes("from '@/providers'")?i=i.replace(/\} from '@\/providers'/,", StoreProvider } from '@/providers'"):i=`import { StoreProvider } from '@/providers';
353
- `+i)),s&&(i=r+`
354
- `+i),!i.includes("<StoreProvider>")){let o=i.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(o){let n=o[1];i=i.replace(o[0],`return (
449
+ `);let i=await d(t);if(!i.includes("@custom-variant dark")){if(i.includes("@import")){let s=i.lastIndexOf("@import"),c=i.indexOf(`
450
+ `,s);i=i.slice(0,c+1)+n+i.slice(c+1)}else i=n+i;await u(t,i)}},Lo=async e=>{let o=await d(e);o.includes("dark:bg-dark")||(o=o.replace(/className="([^"]*)"/,'className="$1 bg-light dark:bg-dark"'),await u(e,o))};var yt=async e=>{let o=A("Setting up Dark Theme..."),t=un.join(e,".next-maker-temp");try{let{isSetup:r,reason:n}=await Ao(e);if(r){o.fail(`Dark Theme is already set up (${n}).`);return}let i=await bo(e);await ko(t,o),await _o(e,t),await jo(e),await Fo(e),await Do(e,t),await Lo(i),o.text="Installing next-themes...",await F(e,"next-themes"),o.text="Formatting code...";let s=await U(e);await D(e,s,"format"),o.succeed(fn.green("Dark Theme setup successfully!"))}catch(r){throw o.fail("Failed to setup Dark Theme."),r}finally{await h(t)}};w();import hn from"node:path";import xn from"picocolors";w();T();import Pt from"node:path";var Ho=async e=>{let o=Pt.join(e,a.STORE),t=Pt.join(e,"package.json");if(l(o))return{isSetup:!0,reason:"src/store directory exists"};if(l(t)){let r=JSON.parse(await d(t));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 e=>{let o=Pt.join(e,a.PROVIDERS_INDEX);if(!await ke(e)||!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.")};w();T();import ne from"node:path";import gn from"degit";import Mo from"node:fs/promises";var Uo=async(e,o)=>{o.text="Fetching assets from starter repo...",await gn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Xo=async(e,o)=>{let t=ne.join(o,"src/providers/StoreProvider.tsx"),r=ne.join(e,a.STORE_PROVIDER);await O(t,r);let n=ne.join(o,"src/store"),i=ne.join(e,a.STORE);await Mo.cp(n,i,{recursive:!0})},Jo=async(e,o)=>{let t=ne.join(o,"src/features/counter"),r=ne.join(e,a.COUNTER_FEATURE);await Mo.cp(t,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)}};w();T();import je from"node:path";var Yo=async e=>{let o=je.join(e,a.PROVIDERS_INDEX),t=await d(o);t.includes("StoreProvider")||(t+=`export * from './StoreProvider';
451
+ `,await u(o,t))},zo=async e=>{let o=je.join(e,"src/providers/RootProvider.tsx");if(l(o)){let t=await d(o),r="'use client';",n=t.includes(r);if(n&&(t=t.replace(r,"").trim()),t.includes("StoreProvider")||(t=t.replace(/import \{ (.*?) \} from '@\/providers';/,"import { $1, StoreProvider } from '@/providers';"),t.includes("StoreProvider")||(t.includes("from '@/providers'")?t=t.replace(/\} from '@\/providers'/,", StoreProvider } from '@/providers'"):t=`import { StoreProvider } from '@/providers';
452
+ `+t)),n&&(t=r+`
453
+ `+t),!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 (
355
454
  <StoreProvider>
356
- ${n}
455
+ ${s}
357
456
  </StoreProvider>
358
- );`),await u(t,i)}}}},Yt=async e=>{let t=[ye.join(e,a.ROOT_PAGE),ye.join(e,"src/app/[locale]/page.tsx")],i="";for(let r of t)if(l(r)){i=r;break}if(i){let r=await d(i);if(r.includes("Counter")||(r=`import { Counter } from '@/features/counter/components/Counter';
359
- `+r),!r.includes("<Counter />")){let s=r.lastIndexOf("</div>"),o=r.lastIndexOf("</main>"),n=o!==-1?o:s;n!==-1&&(r=r.slice(0,n)+`
457
+ );`),await u(o,t)}}}},Wo=async e=>{let o=[je.join(e,a.ROOT_PAGE),je.join(e,"src/app/[locale]/page.tsx")],t="";for(let r of o)if(l(r)){t=r;break}if(t){let r=await d(t);if(r.includes("Counter")||(r=`import { Counter } from '@/features/counter/components/Counter';
458
+ `+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)+`
360
459
  <div className="mt-8">
361
460
  <h2 className="text-2xl font-bold mb-4">Redux Counter</h2>
362
461
  <Counter />
363
462
  </div>
364
- `+r.slice(n),await u(i,r))}}};var He=async e=>{let t=$("Setting up Redux Toolkit..."),i=Io.join(e,".next-maker-temp-redux");try{let{isSetup:r,reason:s}=await jt(e);if(r){t.fail(`Redux is already set up (${s}).`);return}await kt(e),await Lt(i,t),t.text="Copying Redux files...",await Mt(e,i),t.text="Creating Counter feature...",await Ht(e,i),t.text="Updating providers and pages...",await Gt(e),await Ut(e),await Yt(e),t.text="Installing dependencies...",await M(e,"@reduxjs/toolkit"),await M(e,"react-redux"),await M(e,"redux-persist"),await M(e,"react-secure-storage"),t.text="Formatting code...";let o=await G(e);await H(e,o,"format"),t.succeed(Ro.green("Redux Toolkit setup successfully!"))}catch(r){throw t.fail("Failed to setup Redux Toolkit."),r}finally{await S(i)}};T();import $o from"node:path";import _o from"picocolors";T();N();import Se from"node:path";var Xt=async e=>{let t=Se.join(e,a.I18N_DIR),i=Se.join(e,"package.json");if(l(t))return{isSetup:!0,reason:"src/i18n directory exists"};if(l(i)){let r=JSON.parse(await d(i));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:""}},Jt=async e=>{let t=Se.join(e,a.ROOT_LAYOUT),i=Se.join(e,"src/app/[locale]/layout.tsx");if(!l(t)&&!l(i))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx exists.")};T();N();import q from"node:path";import No from"degit";import Ao from"node:fs/promises";var Wt=async(e,t)=>{t.text="Fetching assets from starter repo...",await No("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},zt=async(e,t)=>{let i=q.join(t,"src/i18n"),r=q.join(e,a.I18N_DIR);await Ao.cp(i,r,{recursive:!0});let s=q.join(t,"src/proxy.ts"),o=q.join(e,a.PROXY);await b(s,o);let n=q.join(t,"src/types/i18n.ts"),c=q.join(e,a.I18N_TYPES);await b(n,c);let p=q.join(t,"src/lib/config/app-locales.ts"),m=q.join(e,a.APP_LOCALES);await b(p,m)};T();N();import W from"node:path";import Oo from"node:fs/promises";var Vt=async e=>{let t=W.join(e,a.NEXT_CONFIG);if(l(t)){let i=await d(t);if(!i.includes("createNextIntlPlugin")){i=`import createNextIntlPlugin from 'next-intl/plugin';
365
- `+i;let r=/export default (.*?);/;r.test(i)?i=i.replace(r,`
463
+ `+r.slice(s),await u(t,r))}}};var wt=async e=>{let o=A("Setting up Redux Toolkit..."),t=hn.join(e,".next-maker-temp-redux");try{let{isSetup:r,reason:n}=await Ho(e);if(r){o.fail(`Redux is already set up (${n}).`);return}await Go(e),await Uo(t,o),o.text="Copying Redux files...",await Xo(e,t),o.text="Creating Counter feature...",await Jo(e,t),o.text="Updating providers and pages...",await Yo(e),await zo(e),await Wo(e),o.text="Installing dependencies...",await F(e,"@reduxjs/toolkit"),await F(e,"react-redux"),await F(e,"redux-persist"),await F(e,"react-secure-storage"),o.text="Formatting code...";let i=await U(e);await D(e,i,"format"),o.succeed(xn.green("Redux Toolkit setup successfully!"))}catch(r){throw o.fail("Failed to setup Redux Toolkit."),r}finally{await h(t)}};w();import Sn from"node:path";import Cn from"picocolors";w();T();import Fe from"node:path";var Bo=async e=>{let o=Fe.join(e,a.I18N_DIR),t=Fe.join(e,"package.json");if(l(o))return{isSetup:!0,reason:"src/i18n directory exists"};if(l(t)){let r=JSON.parse(await d(t));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 e=>{let o=Fe.join(e,a.ROOT_LAYOUT),t=Fe.join(e,"src/app/[locale]/layout.tsx");if(!l(o)&&!l(t))throw new Error("Project structure mismatch. Ensure src/app/layout.tsx exists.")};w();T();import ee from"node:path";import yn from"degit";import Pn from"node:fs/promises";var qo=async(e,o)=>{o.text="Fetching assets from starter repo...",await yn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},Ko=async(e,o)=>{let t=ee.join(o,"src/i18n"),r=ee.join(e,a.I18N_DIR);await Pn.cp(t,r,{recursive:!0});let n=ee.join(o,"src/proxy.ts"),i=ee.join(e,a.PROXY);await O(n,i);let s=ee.join(o,"src/types/i18n.ts"),c=ee.join(e,a.I18N_TYPES);await O(s,c);let m=ee.join(o,"src/lib/config/app-locales.ts"),f=ee.join(e,a.APP_LOCALES);await O(m,f)};w();T();import B from"node:path";import wn from"node:fs/promises";var Zo=async e=>{let o=B.join(e,a.NEXT_CONFIG);if(l(o)){let t=await d(o);if(!t.includes("createNextIntlPlugin")){t=`import createNextIntlPlugin from 'next-intl/plugin';
464
+ `+t;let r=/export default (.*?);/;r.test(t)?t=t.replace(r,`
366
465
  const withNextIntl = createNextIntlPlugin();
367
- export default withNextIntl($1);`):(i+=`
466
+ export default withNextIntl($1);`):(t+=`
368
467
  const withNextIntl = createNextIntlPlugin();
369
- `,i+=`export default withNextIntl(nextConfig);
370
- `),await u(t,i)}}},Kt=async e=>{let t=W.join(e,a.TYPES_INDEX);if(l(t)){let i=await d(t);i.includes("./i18n")||(i+=`export * from './i18n';
371
- `,await u(t,i))}},Bt=async e=>{let t=W.join(e,a.CONFIG_INDEX);if(l(t)){let i=await d(t);i.includes("./app-locales")||(i+=`export * from './app-locales';
372
- `,await u(t,i))}},qt=async e=>{let t=W.join(e,"src/providers/RootProvider.tsx");if(l(t)){let i=await d(t),r="'use client';",s=i.includes(r);if(s&&(i=i.replace(r,"").trim()),i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
468
+ `,t+=`export default withNextIntl(nextConfig);
469
+ `),await u(o,t)}}},Qo=async e=>{let o=B.join(e,a.TYPES_INDEX);if(l(o)){let t=await d(o);t.includes("./i18n")||(t+=`export * from './i18n';
470
+ `,await u(o,t))}},er=async e=>{let o=B.join(e,a.CONFIG_INDEX);if(l(o)){let t=await d(o);t.includes("./app-locales")||(t+=`export * from './app-locales';
471
+ `,await u(o,t))}},tr=async e=>{let o=B.join(e,"src/providers/RootProvider.tsx");if(l(o)){let t=await d(o),r="'use client';",n=t.includes(r);if(n&&(t=t.replace(r,"").trim()),t.includes("next-intl")||(t=`import { SupportedLocale } from '@/types/i18n';
373
472
  import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';
374
- `+i),s&&(i=r+`
375
- `+i),!i.includes("locale: SupportedLocale")){let o=/export const RootProvider = \(\{([\s\S]*?)\}: \{([\s\S]*?)\}\) => \{/,n=i.match(o);n&&(i=i.replace(n[0],`export const RootProvider = ({
473
+ `+t),n&&(t=r+`
474
+ `+t),!t.includes("locale: SupportedLocale")){let i=/export const RootProvider = \(\{([\s\S]*?)\}: \{([\s\S]*?)\}\) => \{/,s=t.match(i);s&&(t=t.replace(s[0],`export const RootProvider = ({
376
475
  children,
377
476
  locale,
378
477
  messages,
@@ -380,26 +479,26 @@ import { NextIntlClientProvider, AbstractIntlMessages } from 'next-intl';
380
479
  children: React.ReactNode;
381
480
  locale: SupportedLocale;
382
481
  messages: AbstractIntlMessages;
383
- }) => {`))}if(!i.includes("<NextIntlClientProvider")){let o=i.match(/return\s*(?:\(\s*)?([\s\S]*?)(?:\s*\))?;/);if(o){let n=o[1];if(n.includes("{children}")){let c=n.replace("{children}",`<NextIntlClientProvider locale={locale} messages={messages}>
482
+ }) => {`))}if(!t.includes("<NextIntlClientProvider")){let i=t.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}>
384
483
  {children}
385
- </NextIntlClientProvider>`);i=i.replace(o[0],`return (
484
+ </NextIntlClientProvider>`);t=t.replace(i[0],`return (
386
485
  ${c}
387
- );`)}else i=i.replace(o[0],`return (
486
+ );`)}else t=t.replace(i[0],`return (
388
487
  <NextIntlClientProvider locale={locale} messages={messages}>
389
- ${n}
488
+ ${s}
390
489
  </NextIntlClientProvider>
391
- );`)}}await u(t,i)}},Zt=async e=>{let t=W.join(e,a.ROOT_LAYOUT),i=W.join(e,a.ROOT_PAGE),r=W.join(e,"src/app/[locale]");if(await Oo.mkdir(r,{recursive:!0}),l(t)){let s=W.join(r,"layout.tsx"),o=await d(t);if(o.includes("next-intl")||(o=`import { routing } from '@/i18n/routing';
490
+ );`)}}await u(o,t)}},or=async e=>{let o=B.join(e,a.ROOT_LAYOUT),t=B.join(e,a.ROOT_PAGE),r=B.join(e,"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';
392
491
  import { hasLocale } from 'next-intl';
393
492
  import { notFound } from 'next/navigation';
394
493
  import { setRequestLocale, getMessages } from 'next-intl/server';
395
- `+o),!o.includes("generateStaticParams")){let p=o.indexOf("};",o.indexOf("export const metadata"));if(p!==-1){let m=p+2;o=o.slice(0,m)+`
494
+ `+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)+`
396
495
 
397
496
  export function generateStaticParams() {
398
497
  return routing.locales.map((locale) => ({ locale }));
399
- }`+o.slice(m)}}o=o.replace(/Readonly<\{\s*children:\s*React\.ReactNode;\s*}>/,`Readonly<{
498
+ }`+i.slice(f)}}i=i.replace(/Readonly<\{\s*children:\s*React\.ReactNode;\s*}>/,`Readonly<{
400
499
  children: React.ReactNode;
401
500
  params: Promise<{ locale: string }>;
402
- }>`);let n=/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,c=o.match(n);if(c){c[1]||(o=o.replace("export default function","export default async function")),o=o.replace(/export default (async )?function RootLayout\(\{\s*children,?\s*\}\s*:/,"export default async function RootLayout({ children, params }:");let m=/export default async function RootLayout[\s\S]*?\)\s*\{/,h=o.match(m);if(h&&h.index!==void 0){let y=h.index+h[0].length-1;o=o.slice(0,y+1)+`
501
+ }>`);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)+`
403
502
  const { locale } = await params;
404
503
 
405
504
  if (!hasLocale(routing.locales, locale)) {
@@ -409,26 +508,45 @@ export function generateStaticParams() {
409
508
  setRequestLocale(locale);
410
509
 
411
510
  const messages = await getMessages();
412
- `+o.slice(y+1)}o=o.replace(/<RootProvider>/,"<RootProvider locale={locale} messages={messages}>"),o=o.replace(/<html lang="en"/,"<html lang={locale}")}await u(s,o),await C(t)}if(l(i)){let s=W.join(r,"page.tsx"),o=await d(i);o.includes("next-intl")||(o=`import { SupportedLocale } from '@/types/i18n';
511
+ `+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 P(o)}if(l(t)){let n=B.join(r,"page.tsx"),i=await d(t);i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
413
512
  import { setRequestLocale } from 'next-intl/server';
414
- `+o),o=o.replace(/export default function Home\(\)/,`type Props = {
513
+ `+i),i=i.replace(/export default function Home\(\)/,`type Props = {
415
514
  params: Promise<{ locale: string }>;
416
515
  };
417
516
 
418
- export default async function Home(props: Props)`);let n=o.indexOf("export default async function Home(props: Props) {");if(n!==-1){let c=`
517
+ export default async function Home(props: Props)`);let s=i.indexOf("export default async function Home(props: Props) {");if(s!==-1){let c=`
419
518
  const locale = (await props.params).locale as SupportedLocale;
420
519
  setRequestLocale(locale);
421
- `,p=o.indexOf("{",n);o=o.slice(0,p+1)+c+o.slice(p+1)}await u(s,o),await C(i)}};var Ge=async e=>{let t=$("Setting up Internationalization (next-intl)..."),i=$o.join(e,".next-maker-temp-i18n");try{let{isSetup:r,reason:s}=await Xt(e);if(r){t.fail(`i18n is already set up (${s}).`);return}await Jt(e),await Wt(i,t),t.text="Copying i18n files...",await zt(e,i),t.text="Configuring project structure...",await Vt(e),await Kt(e),await Bt(e),await qt(e),t.text="Migrating to [locale] structure...",await Zt(e),t.text="Installing dependencies...",await M(e,"next-intl"),t.text="Formatting code...";let o=await G(e);await H(e,o,"format"),t.succeed(_o.green("Internationalization setup successfully!"))}catch(r){throw t.fail("Failed to setup Internationalization."),r}finally{await S(i)}};T();import Pe from"node:path";import Fo from"node:fs/promises";import Ue from"picocolors";import ve from"enquirer";T();N();import me from"node:path";var Qt=async e=>{let t=me.join(e,a.FETCH_CLIENT_FILE),i=me.join(e,a.AXIOS_CLIENT_FILE),r=l(t),s=l(i);return r&&s?{status:"both",reason:"Both Fetch and Axios clients are detected"}:r?{status:"fetch",reason:"Fetch client is already setup"}:s?{status:"axios",reason:"Axios client is already setup"}:{status:"none"}},ei=async e=>{let i=[me.join(e,"src/lib"),me.join(e,"src/types"),me.join(e,"src/lib/config")].filter(r=>!l(r));if(i.length>0)throw new Error(`Invalid project structure. Missing directories:
422
- ${i.map(r=>`- ${r}`).join(`
423
- `)}`)};T();N();import P from"node:path";import bo from"degit";import z from"node:fs/promises";var ti=async(e,t)=>{t.text="Downloading assets from starter repository...",await bo("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},ii=async(e,t,i,r)=>{let s=P.join(e,a.HTTP_UTILS),o=P.join(t,a.HTTP_UTILS);await z.cp(P.join(t,a.ERRORS_DIR),P.join(e,a.ERRORS_DIR),{recursive:!0});let n=P.join(e,a.APP_APIS);l(n)||await b(P.join(t,a.APP_APIS),n);let c=P.join(e,a.CONSTANTS);if(!l(c))await b(P.join(t,a.CONSTANTS),c);else{let m=await d(c),h=!1;m.includes("API_RESPONSE_DATA_KEY")||(m+=`
520
+ `,m=i.indexOf("{",s);i=i.slice(0,m+1)+c+i.slice(m+1)}await u(n,i),await P(t)}};var St=async e=>{let o=A("Setting up Internationalization (next-intl)..."),t=Sn.join(e,".next-maker-temp-i18n");try{let{isSetup:r,reason:n}=await Bo(e);if(r){o.fail(`i18n is already set up (${n}).`);return}await Vo(e),await qo(t,o),o.text="Copying i18n files...",await Ko(e,t),o.text="Configuring project structure...",await Zo(e),await Qo(e),await er(e),await tr(e),o.text="Migrating to [locale] structure...",await or(e),o.text="Installing dependencies...",await F(e,"next-intl"),o.text="Formatting code...";let i=await U(e);await D(e,i,"format"),o.succeed(Cn.green("Internationalization setup successfully!"))}catch(r){throw o.fail("Failed to setup Internationalization."),r}finally{await h(t)}};w();import De from"node:path";import Tn from"node:fs/promises";import Ct from"picocolors";import Le from"enquirer";w();T();import Ce from"node:path";var rr=async e=>{let o=Ce.join(e,a.FETCH_CLIENT_FILE),t=Ce.join(e,a.AXIOS_CLIENT_FILE),r=l(o),n=l(t);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 e=>{let t=[Ce.join(e,"src/lib"),Ce.join(e,"src/types"),Ce.join(e,"src/lib/config")].filter(r=>!l(r));if(t.length>0)throw new Error(`Invalid project structure. Missing directories:
521
+ ${t.map(r=>`- ${r}`).join(`
522
+ `)}`)};w();T();import y from"node:path";import vn from"degit";import V from"node:fs/promises";var nr=async(e,o)=>{o.text="Downloading assets from starter repository...",await vn("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(e)},sr=async(e,o,t,r)=>{let n=y.join(e,a.HTTP_UTILS),i=y.join(o,a.HTTP_UTILS);await V.cp(y.join(o,a.ERRORS_DIR),y.join(e,a.ERRORS_DIR),{recursive:!0});let s=y.join(e,a.APP_APIS);l(s)||await O(y.join(o,a.APP_APIS),s);let c=y.join(e,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+=`
424
523
  export const API_RESPONSE_DATA_KEY = 'data';
425
- `,h=!0),m.includes("SAVE_AUTH_TOKENS")||(m+=`
524
+ `,x=!0),f.includes("SAVE_AUTH_TOKENS")||(f+=`
426
525
  export const SAVE_AUTH_TOKENS = false;
427
- `,h=!0),h&&await u(c,m)}let p=P.join(e,a.STORAGE_SERVICE);if(l(p)||await z.cp(P.join(t,a.STORAGE_SERVICE),p,{recursive:!0}),await z.cp(P.join(t,a.COMMON_TYPES_DIR),P.join(e,a.COMMON_TYPES_DIR),{recursive:!0}),await z.cp(P.join(t,a.UTILITY_TYPES_DIR),P.join(e,a.UTILITY_TYPES_DIR),{recursive:!0}),await b(P.join(o,"token-store.ts"),P.join(s,"token-store.ts")),await b(P.join(o,"client-utils.ts"),P.join(s,"client-utils.ts")),r&&r.length>0)for(let m of r){let h=P.join(e,m==="fetch"?a.FETCH_CLIENT:a.AXIOS_CLIENT);await S(h)}for(let m of i)m==="fetch"?await z.cp(P.join(t,a.FETCH_CLIENT),P.join(e,a.FETCH_CLIENT),{recursive:!0}):await z.cp(P.join(t,a.AXIOS_CLIENT),P.join(e,a.AXIOS_CLIENT),{recursive:!0});await b(P.join(o,"index.ts"),P.join(s,"index.ts")),await b(P.join(t,a.HTTP_TYPES),P.join(e,a.HTTP_TYPES))},oi=async e=>{let{isFileUsed:t,isStringUsed:i}=await Promise.resolve().then(()=>(fe(),et));await S(P.join(e,a.HTTP_UTILS));let r=P.join(e,a.STORAGE_SERVICE);l(r)&&(await i(e,"SecureStorageService",[r])||await S(r));let s=P.join(e,a.CONSTANTS);if(l(s)){let p=await d(s),m=!1;await i(e,"API_RESPONSE_DATA_KEY",[s])||(p=p.replace(/export const API_RESPONSE_DATA_KEY = .*;\n?/g,""),m=!0),await i(e,"SAVE_AUTH_TOKENS",[s])||(p=p.replace(/export const SAVE_AUTH_TOKENS = .*;\n?/g,""),m=!0),m&&(p=p.replace(/\n\s*\n/g,`
526
+ `,x=!0),x&&await u(c,f)}let m=y.join(e,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(e,a.COMMON_TYPES_DIR),{recursive:!0}),await V.cp(y.join(o,a.UTILITY_TYPES_DIR),y.join(e,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(e,f==="fetch"?a.FETCH_CLIENT:a.AXIOS_CLIENT);await h(x)}for(let f of t)f==="fetch"?await V.cp(y.join(o,a.FETCH_CLIENT),y.join(e,a.FETCH_CLIENT),{recursive:!0}):await V.cp(y.join(o,a.AXIOS_CLIENT),y.join(e,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(e,a.HTTP_TYPES))},ar=async e=>{let{isFileUsed:o,isStringUsed:t}=await Promise.resolve().then(()=>(Re(),_t));await h(y.join(e,a.HTTP_UTILS));let r=y.join(e,a.STORAGE_SERVICE);l(r)&&(await t(e,"SecureStorageService",[r])||await h(r));let n=y.join(e,a.CONSTANTS);if(l(n)){let m=await d(n),f=!1;await t(e,"API_RESPONSE_DATA_KEY",[n])||(m=m.replace(/export const API_RESPONSE_DATA_KEY = .*;\n?/g,""),f=!0),await t(e,"SAVE_AUTH_TOKENS",[n])||(m=m.replace(/export const SAVE_AUTH_TOKENS = .*;\n?/g,""),f=!0),f&&(m=m.replace(/\n\s*\n/g,`
428
527
 
429
528
  `).trim()+`
430
- `,await u(s,p))}let o=P.join(e,a.ERRORS_DIR);if(l(o)){let p=await z.readdir(o),m=!1;for(let h of p){let y=P.parse(h).name;if(await t(e,y,[P.join(o,h)])){m=!0;break}}m||await S(o)}let n=P.join(e,a.COMMON_TYPES_DIR);l(n)&&(await z.readdir(n)).length===0&&await S(n);let c=P.join(e,a.UTILITY_TYPES_DIR);l(c)&&(await z.readdir(c)).length===0&&await S(c)};fe();var Ye=async e=>{let t=$("Checking HTTP Client setup..."),i=Pe.join(e,".next-maker-temp-http");try{let{status:r,reason:s}=await Qt(e);t.stop();let o=await jo(r,s);if(o.type==="cancel"){console.log(Ue.yellow("Setup cancelled."));return}if(t.start("Setting up HTTP client(s)..."),await ei(e),await ti(i,t),o.type==="replace"&&o.fromClient&&(t.text="Migrating client usages...",await $e(e,o.fromClient,o.clients[0])),o.type!=="remove-both"&&o.type!=="remove-one"){t.text="Copying client files...";let w=o.type==="replace"&&o.fromClient?[o.fromClient]:void 0;await ii(e,i,o.clients,w)}if(o.type==="remove-one"||o.type==="remove-both"){t.text="Removing client files...";let{PROJECT_PATHS:w}=await Promise.resolve().then(()=>(N(),Ze));for(let I of o.clients){let F=Pe.join(e,I==="fetch"?w.FETCH_CLIENT:w.AXIOS_CLIENT);await S(F)}ri(r,o).length===0&&(t.text="Performing full cleanup...",await oi(e),await _e(e))}let n=ri(r,o);n.length>0&&(t.text="Configuring client...",await Re(e,n),await Ne(e),await Ae(e),await Oe(e)),await oe(e,n),t.text="Managing dependencies...";let c=Pe.join(e,"package.json"),p=JSON.parse(await Fo.readFile(c,"utf-8")),m={...p.dependencies,...p.devDependencies};n.includes("axios")?m.axios||(t.text="Installing Axios...",await M(e,"axios")):m.axios&&(t.text="Uninstalling Axios...",await Ee(e,"axios"));let h=Pe.join(e,"src/services/storage");n.length>0||l(h)?m["react-secure-storage"]||(t.text="Installing react-secure-storage...",await M(e,"react-secure-storage")):m["react-secure-storage"]&&(t.text="Uninstalling react-secure-storage...",await Ee(e,"react-secure-storage")),t.text="Formatting code...";let x=await G(e);await H(e,x,"format"),t.succeed(Ue.green(ko(o)))}catch(r){throw t.fail("Failed to setup HTTP Client."),r}finally{await S(i)}};async function jo(e,t){if(e==="none"){let{choice:r}=await ve.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(e==="fetch"){let{action:r}=await ve.prompt({type:"select",name:"action",message:`${t}. 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(e==="axios"){let{action:r}=await ve.prompt({type:"select",name:"action",message:`${t}. 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(Ue.yellow(`\u2716 ${t}`));let{action:i}=await ve.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 i==="cancel"?{type:"cancel",clients:[]}:i==="remove-fetch"?{type:"remove-one",clients:["fetch"]}:i==="remove-axios"?{type:"remove-one",clients:["axios"]}:i==="remove-both"?{type:"remove-both",clients:["fetch","axios"]}:{type:"cancel",clients:[]}}function ri(e,t){return t.type==="install"?t.clients:t.type==="add"?[...e==="fetch"?["fetch"]:["axios"],...t.clients]:t.type==="replace"?t.clients:t.type==="remove-one"?e==="both"?t.clients[0]==="fetch"?["axios"]:["fetch"]:[]:[]}function ko(e){if(e.type==="install")return`HTTP Client (${e.clients.map(i=>i==="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 t=e.fromClient==="fetch"?"Fetch":"Axios",i=e.clients[0]==="fetch"?"Fetch":"Axios";return`Replaced ${t} with ${i} 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!"}var{prompt:Lo}=Do,ni=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 + next-themes)").option("--redux","Setup Redux Toolkit").option("--i18n","Setup next-intl for internationalization").action(async t=>{try{if(f(we.cyan(`
529
+ `,await u(n,m))}let i=y.join(e,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(e,S,[y.join(i,x)])){f=!0;break}}f||await h(i)}let s=y.join(e,a.COMMON_TYPES_DIR);l(s)&&(await V.readdir(s)).length===0&&await h(s);let c=y.join(e,a.UTILITY_TYPES_DIR);l(c)&&(await V.readdir(c)).length===0&&await h(c)};Re();var vt=async e=>{let o=A("Checking HTTP Client setup..."),t=De.join(e,".next-maker-temp-http");try{let{status:r,reason:n}=await rr(e);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(e),await nr(t,o),i.type==="replace"&&i.fromClient&&(o.text="Migrating client usages...",await Ve(e,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(e,t,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(e,Te==="fetch"?M.FETCH_CLIENT:M.AXIOS_CLIENT);await h(Ee)}cr(r,i).length===0&&(o.text="Performing full cleanup...",await ar(e),await qe(e))}let s=cr(r,i);s.length>0&&(o.text="Configuring client...",await Ye(e,s),await ze(e),await We(e),await Be(e)),await ae(e,s),o.text="Managing dependencies...";let c=De.join(e,"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(e,"axios")):f.axios&&(o.text="Uninstalling Axios...",await Xe(e,"axios"));let x=De.join(e,"src/services/storage");s.length>0||l(x)?f["react-secure-storage"]||(o.text="Installing react-secure-storage...",await F(e,"react-secure-storage")):f["react-secure-storage"]&&(o.text="Uninstalling react-secure-storage...",await Xe(e,"react-secure-storage")),o.text="Formatting code...";let v=await U(e);await D(e,v,"format"),o.succeed(Ct.green(In(i)))}catch(r){throw o.fail("Failed to setup HTTP Client."),r}finally{await h(t)}};async function En(e,o){if(e==="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(e==="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(e==="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:t}=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 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 cr(e,o){return o.type==="install"?o.clients:o.type==="add"?[...e==="fetch"?["fetch"]:["axios"],...o.clients]:o.type==="replace"?o.clients:o.type==="remove-one"?e==="both"?o.clients[0]==="fetch"?["axios"]:["fetch"]:[]:[]}function In(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 o=e.fromClient==="fetch"?"Fetch":"Axios",t=e.clients[0]==="fetch"?"Fetch":"Axios";return`Replaced ${o} 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!"}var{prompt:Rn}=Nn,pr=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 + next-themes)").option("--redux","Setup Redux Toolkit").option("--i18n","Setup next-intl for internationalization").action(async o=>{try{if(p(He.cyan(`
431
530
  \u{1F527} Setup Wizard
432
- `)),t.httpClient||t.darkTheme||t.redux||t.i18n){t.httpClient&&await Ye(process.cwd()),t.darkTheme&&await Le(process.cwd()),t.redux&&await He(process.cwd()),t.i18n&&await Ge(process.cwd());return}let r=(await Lo([{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"){f(we.yellow("Setup cancelled."));return}r==="dark-theme"?await Le(process.cwd()):r==="redux"?await He(process.cwd()):r==="http-client"?await Ye(process.cwd()):r==="i18n"?await Ge(process.cwd()):(f(we.yellow(`
433
- \u26A0\uFE0F ${r} setup is not implemented yet.`)),f(we.dim("This feature will be available in a future update.")))}catch(i){v.fail("Setup failed"),R(`${i}`),process.exit(1)}})};var si=e=>{st(e),ni(e),ft(e),St(e),Tt(e)};var Ho=process.emitWarning;process.emitWarning=function(e,t,i,r){if(!(typeof e=="string"&&e.includes("--localstorage-file")&&e.includes("was provided without a valid path")))return Ho.apply(process,arguments)};async function Go(){Be({logger:t=>ue(t)});let e=new Mo;e.name("next-maker").description("Teispace Next.js Project Generator").version("1.0.0"),si(e),e.parse()}Go().catch(e=>{let t=e&&typeof e=="object"&&"message"in e?e.message:String(e);ue(`Unexpected error: ${t}`)});
531
+ `)),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(`
532
+ \u26A0\uFE0F ${r} setup is not implemented yet.`)),p(He.dim("This feature will be available in a future update.")))}catch(t){g.fail("Setup failed"),C(`${t}`),process.exit(1)}})};import G from"picocolors";import lr from"node:path";import $n from"enquirer";var{prompt:An}=$n,mr=async e=>{let o=[];e||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 t=await An(o);return{pageName:e||t.pageName,withLoading:t.withLoading,withError:t.withError}};W();var dr=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(o,t)=>{try{let r=process.cwd();p(G.cyan(`
533
+ \u{1F4C4} Page Generator
534
+ `)),g.start("Detecting project setup...");let n=await _(r);g.succeed("Project setup detected"),p(G.dim(` i18n: ${n.hasI18n?"\u2713":"\u2717"}
535
+ `));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:t.dynamic,withLoading:t.loading??i.withLoading,withError:t.error??i.withError}),g.succeed("Page files generated"),g.start("Registering route...");let x=t.dynamic?`/${s}/[${t.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=t.dynamic?lr.join(m,s,`[${t.dynamic}]`):lr.join(m,s);p(G.green(`
536
+ \u2728 Page '${s}' created successfully!
537
+ `)),p(G.dim("Generated files:")),p(G.dim(` \u{1F4C2} ${S}/`)),p(G.dim(" \u251C\u2500\u2500 page.tsx")),(t.loading??i.withLoading)&&p(G.dim(" \u251C\u2500\u2500 loading.tsx")),(t.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 e=>{let o=[];e||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 t=await On(o);return{componentName:e||t.componentName,isClient:t.isClient}};W();var fr=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)").action(async(o,t)=>{try{let r=process.cwd();p(q.cyan(`
538
+ \u{1F9E9} Component Generator
539
+ `)),g.start("Detecting project setup..."),await _(r),g.succeed("Project setup detected");let n=await ur(o),i=N(n.componentName),s=t.client??n.isClient,c=t.i18n??!1;g.start("Generating component..."),await st({name:n.componentName,projectPath:r,isClient:s||c,hasI18n:c,featurePath:t.feature}),g.succeed("Component generated");let m=t.feature?`${t.feature}/components/${i}.tsx`:`src/components/common/${i}/${i}.tsx`;p(q.green(`
540
+ \u2728 Component '${i}' created successfully!
541
+ `)),p(q.dim(` \u{1F4C4} ${m}`)),t.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:")),t.feature?p(q.dim(` import { ${i} } from '${t.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 e=>{let o=[];e||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 t=await _n(o);return{code:e||t.code,name:t.name,country:t.country,flag:t.flag,copyTranslations:t.copyTranslations}};W();w();import jn from"node:path";var hr=e=>{e.command("locale [code]").description("Add a new locale/language").option("--copy-translations","Copy translations from English instead of empty values").action(async(o,t)=>{try{let r=process.cwd();p(Y.cyan(`
542
+ \u{1F30D} Locale Generator
543
+ `)),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(`
544
+ Run: npx @teispace/next-maker setup --i18n
545
+ `)),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:t.copyTranslations??i.copyTranslations}),g.succeed("Locale added"),p(Y.green(`
546
+ \u2728 Locale '${i.code}' (${i.name}) added successfully!
547
+ `)),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 e=>e?{hookName:e}:await Dn({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 yr=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)").action(async(o,t)=>{try{let r=process.cwd();p(ve.cyan(`
548
+ \u{1FA9D} Hook Generator
549
+ `));let n=await xr(o),s=`use${N(n.hookName)}`;g.start("Generating hook..."),await pt({name:n.hookName,projectPath:r,isClient:t.client??!0,featurePath:t.feature}),g.succeed("Hook generated");let c=t.feature?`${t.feature}/hooks/${s}.ts`:`src/hooks/${s}.ts`;p(ve.green(`
550
+ \u2728 Hook '${s}' created successfully!
551
+ `)),p(ve.dim(` \u{1F4C4} ${c}`)),p(""),p(ve.cyan("Usage:"));let m=t.feature?`${t.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=e=>{Vt(e),pr(e),Co(e),To(e),Ro(e),dr(e),fr(e),hr(e),yr(e)};var Hn=process.emitWarning;process.emitWarning=function(e,o,t,r){if(!(typeof e=="string"&&e.includes("--localstorage-file")&&e.includes("was provided without a valid path")))return Hn.apply(process,arguments)};async function Gn(){At({logger:o=>Ne(o)});let e=new Ln;e.name("next-maker").description("Teispace Next.js Project Generator").version("1.0.0"),Pr(e),e.parse()}Gn().catch(e=>{let o=e&&typeof e=="object"&&"message"in e?e.message:String(e);Ne(`Unexpected error: ${o}`)});
434
552
  //# sourceMappingURL=index.js.map