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