@qlover/create-app 0.12.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/next-app/next.config.ts +4 -3
- package/dist/templates/next-app/package.json +12 -9
- package/dist/templates/next-app/src/app/[locale]/login/LoginForm.tsx +2 -3
- package/dist/templates/next-app/src/base/cases/DialogErrorPlugin.ts +6 -4
- package/dist/templates/next-app/src/base/cases/RequestEncryptPlugin.ts +14 -10
- package/dist/templates/next-app/src/base/cases/StringEncryptor.ts +2 -2
- package/dist/templates/next-app/src/base/port/I18nServiceInterface.ts +1 -4
- package/dist/templates/next-app/src/base/services/I18nService.ts +6 -2
- package/dist/templates/next-app/src/base/services/adminApi/AdminApiRequester.ts +11 -7
- package/dist/templates/next-app/src/base/services/adminApi/AdminLocalesApi.ts +11 -10
- package/dist/templates/next-app/src/base/services/adminApi/AdminUserApi.ts +16 -12
- package/dist/templates/next-app/src/base/services/appApi/AppApiPlugin.ts +19 -19
- package/dist/templates/next-app/src/base/services/appApi/AppApiRequester.ts +26 -21
- package/dist/templates/next-app/src/base/services/appApi/AppUserApi.ts +15 -6
- package/dist/templates/next-app/src/base/services/appApi/AppUserApiBootstrap.ts +12 -14
- package/dist/templates/next-app/src/core/bootstraps/BootstrapServer.ts +34 -17
- package/dist/templates/next-app/src/server/NextApiServer.ts +10 -4
- package/dist/templates/next-app/src/server/PasswordEncrypt.ts +2 -2
- package/dist/templates/next-app/src/server/controllers/UserController.ts +2 -2
- package/dist/templates/next-app/src/server/port/ServerInterface.ts +2 -2
- package/dist/templates/next-app/src/server/services/AdminAuthPlugin.ts +6 -7
- package/dist/templates/next-app/src/server/services/UserService.ts +2 -2
- package/dist/templates/next-app/src/uikit/components/BootstrapsProvider.tsx +11 -47
- package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +3 -2
- package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +6 -1
- package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +21 -61
- package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +29 -51
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapClient.test.ts +8 -26
- package/dist/templates/react-app/__tests__/src/main.test.tsx +2 -2
- package/dist/templates/react-app/config/IOCIdentifier.ts +1 -1
- package/dist/templates/react-app/docs/en/test-guide.md +5 -5
- package/dist/templates/react-app/docs/zh/test-guide.md +5 -5
- package/dist/templates/react-app/package.json +2 -1
- package/dist/templates/react-app/src/base/apis/AiApi.ts +20 -12
- package/dist/templates/react-app/src/base/apis/feApi/FeApi.ts +14 -5
- package/dist/templates/react-app/src/base/apis/feApi/FeApiBootstarp.ts +26 -13
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +30 -34
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +20 -17
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +11 -5
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +19 -6
- package/dist/templates/react-app/src/base/cases/RequestLogger.ts +11 -11
- package/dist/templates/react-app/src/base/services/BaseLayoutService.ts +11 -5
- package/dist/templates/react-app/src/base/services/UserBootstrap.ts +6 -7
- package/dist/templates/react-app/src/base/services/UserService.ts +1 -5
- package/dist/templates/react-app/src/core/clientIoc/ClientIOCRegister.ts +6 -7
- package/dist/templates/react-app/src/main.tsx +1 -1
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -5
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +3 -1
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +6 -2
- package/dist/templates/react-app/src/pages/base/MessagePage.tsx +34 -3
- package/dist/templates/react-app/src/uikit/bridges/ExecutorPageBridge.ts +13 -7
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +6 -1
- package/dist/templates/react-app/src/uikit/components/MessageBaseList.tsx +26 -11
- package/dist/templates/react-app/src/uikit/components/chatMessage/ChatMessageBridge.ts +1 -1
- package/dist/templates/react-app/src/uikit/components/chatMessage/FocusBar.tsx +3 -1
- package/dist/templates/react-app/src/uikit/components/chatMessage/MessageApi.ts +16 -7
- package/dist/templates/react-app/src/vite-env.d.ts +1 -1
- package/dist/templates/react-app/tsconfig.e2e.json +5 -2
- package/dist/templates/react-app/tsconfig.json +7 -0
- package/dist/templates/react-app/tsconfig.node.json +4 -2
- package/dist/templates/react-app/tsconfig.test.json +4 -1
- package/package.json +3 -3
- package/dist/templates/react-app/src/base/cases/AppError.ts +0 -10
- package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +0 -20
- package/dist/templates/react-app/src/base/services/UserGatewayPlugin.ts +0 -20
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -8,4 +8,4 @@ ${t}`,dn=Object.getOwnPropertyDescriptor(Function.prototype,"toString"),_n=Objec
|
|
|
8
8
|
`))this.#e+=Math.max(1,Math.ceil(Ye(D,{countAnsiEscapeCodes:!0})/t))}get isEnabled(){return this.#a&&!this.#F}set isEnabled(t){if(typeof t!="boolean")throw new TypeError("The `isEnabled` option must be a boolean");this.#a=t}get isSilent(){return this.#F}set isSilent(t){if(typeof t!="boolean")throw new TypeError("The `isSilent` option must be a boolean");this.#F=t}frame(){let t=Date.now();(this.#i===-1||t-this.#c>=this.interval)&&(this.#i=++this.#i%this.#D.frames.length,this.#c=t);let{frames:r}=this.#D,u=r[this.#i];this.color&&(u=d[this.color](u));let i=typeof this.#s=="string"&&this.#s!==""?this.#s+" ":"",D=typeof this.text=="string"?" "+this.text:"",o=typeof this.#o=="string"&&this.#o!==""?" "+this.#o:"";return i+u+D+o}clear(){if(!this.#a||!this.#u.isTTY)return this;this.#u.cursorTo(0);for(let t=0;t<this.#n;t++)t>0&&this.#u.moveCursor(0,-1),this.#u.clearLine(1);return(this.#l||this.lastIndent!==this.#l)&&this.#u.cursorTo(this.#l),this.lastIndent=this.#l,this.#n=0,this}render(){return this.#F?this:(this.clear(),this.#u.write(this.frame()),this.#n=this.#e,this)}start(t){return t&&(this.text=t),this.#F?this:this.#a?this.isSpinning?this:(this.#t.hideCursor&&$e.hide(this.#u),this.#t.discardStdin&&z.default.stdin.isTTY&&(this.#r=!0,Je.start()),this.render(),this.#f=setInterval(this.render.bind(this),this.interval),this):(this.text&&this.#u.write(`- ${this.text}
|
|
9
9
|
`),this)}stop(){return this.#a?(clearInterval(this.#f),this.#f=void 0,this.#i=0,this.clear(),this.#t.hideCursor&&$e.show(this.#u),this.#t.discardStdin&&z.default.stdin.isTTY&&this.#r&&(Je.stop(),this.#r=!1),this):this}succeed(t){return this.stopAndPersist({symbol:Y.success,text:t})}fail(t){return this.stopAndPersist({symbol:Y.error,text:t})}warn(t){return this.stopAndPersist({symbol:Y.warning,text:t})}info(t){return this.stopAndPersist({symbol:Y.info,text:t})}stopAndPersist(t={}){if(this.#F)return this;let r=t.prefixText??this.#s,u=this.#E(r," "),i=t.symbol??" ",D=t.text??this.text,s=typeof D=="string"?(i?" ":"")+D:"",a=t.suffixText??this.#o,l=this.#g(a," "),p=u+i+s+l+`
|
|
10
10
|
`;return this.stop(),this.#u.write(p),this}};function tr(e){return new Ze(e)}async function rr(e,t){let r=typeof e=="function",u=typeof e.then=="function";if(!r&&!u)throw new TypeError("Parameter `action` must be a Function or a Promise");let{successText:i,failText:D}=typeof t=="object"?t:{successText:void 0,failText:void 0},o=tr(t).start();try{let a=await(r?e(o):e);return o.succeed(i===void 0?void 0:typeof i=="string"?i:i(a)),a}catch(s){throw o.fail(D===void 0?void 0:typeof D=="string"?D:D(s)),s}}var bt=require("fs");var S=require("path"),A=require("fs"),cr=h(lr(),1);var _e=require("fs"),J=class{static ensureDir(t){(0,_e.existsSync)(t)||(0,_e.mkdirSync)(t,{recursive:!0})}};var{copyFile:rs,stat:us}=A.promises,me=class e{constructor(t,r=e.IGNORE_FILE){this.ignoreTargetPath=t;this.ignoreFile=r}static IGNORE_FILE=".gitignore.template";getIg(t=this.ignoreTargetPath){let r=(0,S.join)(t,this.ignoreFile);if(!(0,A.existsSync)(r))return;let D=(0,A.readFileSync)(r,"utf8").split(`
|
|
11
|
-
`).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#"));return(0,cr.default)().add(D)}async copyFiles(t,r,u,i){let D=await A.promises.readdir(t);await Promise.all(D.map(async o=>{let s=(0,S.join)(t,o),a=(0,S.join)(r,o);if(u&&u.ignores(o))return;if(J.ensureDir((0,S.dirname)(a)),(await us(s)).isDirectory())await this.copyFiles(s,a,u,i);else{if(i&&await i(s,a))return;await rs(s,a)}}))}copyPaths({sourcePath:t,targetPath:r,copyCallback:u}){J.ensureDir(r);let i=this.getIg();return this.copyFiles(t,r,i,u)}};var k=require("fs"),kD=h(LD(),1),xe=class{constructor(){}isJSONFilePath(t){return t.endsWith(".json")||t.endsWith(".json.template")}isTemplateFilePath(t){return t.endsWith(".template")}getRealTemplateFilePath(t){return t.replace(".template","")}readFile(t){return(0,k.readFileSync)(t,"utf-8")}readJSONFile(t){return JSON.parse(this.readFile(t))}writeFile(t,r){(0,k.writeFileSync)(this.getRealTemplateFilePath(t),r,{encoding:"utf-8"})}replaceFile(t,r){let u=this.readFile(t);return Object.keys(r).forEach(i=>{let D=r[i];u=u.replace(new RegExp(`\\[TPL:${i}\\]`,"g"),typeof D=="string"?D:JSON.stringify(D))}),u}mergeJSONFile(t,r){let u=this.readJSONFile(t),i=(0,kD.default)(r,u);this.writeFile(t,JSON.stringify(i,null,2))}composeConfigFile(t,r,u){if(this.isTemplateFilePath(r)){let i=this.replaceFile(r,t);if(this.isJSONFilePath(r)&&this.isJSONFilePath(u)){let D=this.getRealTemplateFilePath(u);return(0,k.existsSync)(D)?(this.mergeJSONFile(D,JSON.parse(i)),!0):(this.writeFile(D,i),!0)}return this.writeFile(u,i),!0}return!1}};var $D=["pack-app"],ye=class{ora;context;subPackages;copyer;compose;constructor(t){let r=t.options?.templateRootPath;if(!r)throw new Error("template path not exit");if(!(0,bt.existsSync)(r))throw new Error("template path not exit");this.ora=rr,this.context=new UD.ScriptContext("create-app",t),this.subPackages=["node-lib","react-app","next-app"],this.copyer=new me((0,x.join)(this.context.options.configsRootPath,"_common")),this.compose=new xe}get logger(){return this.context.logger}async steps(t){try{return await WD.default.prompt(t)}catch(r){throw r.isTtyError,this.logger.error(r),r}}async action({label:t,task:r}){let u=r();u instanceof Promise||(u=Promise.resolve(u));let i=t;return this.ora(u,i),u}isPackageTemplate(t){return $D.includes(t)}async getGeneratorContext(){let t=Ot(this.subPackages,$D),r=await this.steps(t);if(this.isPackageTemplate(r.template)){let u=wt(this.subPackages),i=await this.steps(u);Object.assign(r,i)}return r.targetPath=(0,x.join)(process.cwd(),r.projectName),r.releasePath=r.releasePath||"src",r}async generate(){let t=await this.getGeneratorContext();if(this.logger.debug("context is:",t,this.context.options.templateRootPath),t.subPackages){await this.action({label:"Generate Directories(subPackages)",task:async()=>{await this.generateTemplateDir(t),await this.generateSubPackages(t),await this.generateConfigs(t,t.targetPath,"_common")}});return}await this.action({label:"Generate Directory",task:async()=>{await this.generateTemplateDir(t),await this.generateConfigs(t,t.targetPath,"_common"),await this.generateConfigs(t,t.targetPath,t.template)}})}async generateConfigs(t,r,u){let i=(a,l)=>(this.logger.debug("copyCallback",a,l),this.compose.composeConfigFile(t,a,l)),{configsRootPath:D,config:o}=this.context.options;if(!o){this.logger.debug("no copy config files");return}let s=(0,x.join)(D,u);if(!(0,bt.existsSync)(s)){this.logger.debug(`Config path not found: ${s}`);return}await this.copyer.copyPaths({sourcePath:s,targetPath:r,copyCallback:i})}generateTemplateDir(t){return this.copyer.copyPaths({sourcePath:(0,x.join)(this.context.options.templateRootPath,t.template),targetPath:t.targetPath})}async generateSubPackages(t){let{packagesNames:r="packages",subPackages:u=[],targetPath:i=""}=t,{templateRootPath:D}=this.context.options;for(let o of u){let s=(0,x.join)(D,o),a=(0,x.join)(i,r,o);this.logger.debug("copy sub package",s,a),await this.copyer.copyPaths({sourcePath:s,targetPath:a})}}};var At={name:"@qlover/create-app",version:"0.
|
|
11
|
+
`).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#"));return(0,cr.default)().add(D)}async copyFiles(t,r,u,i){let D=await A.promises.readdir(t);await Promise.all(D.map(async o=>{let s=(0,S.join)(t,o),a=(0,S.join)(r,o);if(u&&u.ignores(o))return;if(J.ensureDir((0,S.dirname)(a)),(await us(s)).isDirectory())await this.copyFiles(s,a,u,i);else{if(i&&await i(s,a))return;await rs(s,a)}}))}copyPaths({sourcePath:t,targetPath:r,copyCallback:u}){J.ensureDir(r);let i=this.getIg();return this.copyFiles(t,r,i,u)}};var k=require("fs"),kD=h(LD(),1),xe=class{constructor(){}isJSONFilePath(t){return t.endsWith(".json")||t.endsWith(".json.template")}isTemplateFilePath(t){return t.endsWith(".template")}getRealTemplateFilePath(t){return t.replace(".template","")}readFile(t){return(0,k.readFileSync)(t,"utf-8")}readJSONFile(t){return JSON.parse(this.readFile(t))}writeFile(t,r){(0,k.writeFileSync)(this.getRealTemplateFilePath(t),r,{encoding:"utf-8"})}replaceFile(t,r){let u=this.readFile(t);return Object.keys(r).forEach(i=>{let D=r[i];u=u.replace(new RegExp(`\\[TPL:${i}\\]`,"g"),typeof D=="string"?D:JSON.stringify(D))}),u}mergeJSONFile(t,r){let u=this.readJSONFile(t),i=(0,kD.default)(r,u);this.writeFile(t,JSON.stringify(i,null,2))}composeConfigFile(t,r,u){if(this.isTemplateFilePath(r)){let i=this.replaceFile(r,t);if(this.isJSONFilePath(r)&&this.isJSONFilePath(u)){let D=this.getRealTemplateFilePath(u);return(0,k.existsSync)(D)?(this.mergeJSONFile(D,JSON.parse(i)),!0):(this.writeFile(D,i),!0)}return this.writeFile(u,i),!0}return!1}};var $D=["pack-app"],ye=class{ora;context;subPackages;copyer;compose;constructor(t){let r=t.options?.templateRootPath;if(!r)throw new Error("template path not exit");if(!(0,bt.existsSync)(r))throw new Error("template path not exit");this.ora=rr,this.context=new UD.ScriptContext("create-app",t),this.subPackages=["node-lib","react-app","next-app"],this.copyer=new me((0,x.join)(this.context.options.configsRootPath,"_common")),this.compose=new xe}get logger(){return this.context.logger}async steps(t){try{return await WD.default.prompt(t)}catch(r){throw r.isTtyError,this.logger.error(r),r}}async action({label:t,task:r}){let u=r();u instanceof Promise||(u=Promise.resolve(u));let i=t;return this.ora(u,i),u}isPackageTemplate(t){return $D.includes(t)}async getGeneratorContext(){let t=Ot(this.subPackages,$D),r=await this.steps(t);if(this.isPackageTemplate(r.template)){let u=wt(this.subPackages),i=await this.steps(u);Object.assign(r,i)}return r.targetPath=(0,x.join)(process.cwd(),r.projectName),r.releasePath=r.releasePath||"src",r}async generate(){let t=await this.getGeneratorContext();if(this.logger.debug("context is:",t,this.context.options.templateRootPath),t.subPackages){await this.action({label:"Generate Directories(subPackages)",task:async()=>{await this.generateTemplateDir(t),await this.generateSubPackages(t),await this.generateConfigs(t,t.targetPath,"_common")}});return}await this.action({label:"Generate Directory",task:async()=>{await this.generateTemplateDir(t),await this.generateConfigs(t,t.targetPath,"_common"),await this.generateConfigs(t,t.targetPath,t.template)}})}async generateConfigs(t,r,u){let i=(a,l)=>(this.logger.debug("copyCallback",a,l),this.compose.composeConfigFile(t,a,l)),{configsRootPath:D,config:o}=this.context.options;if(!o){this.logger.debug("no copy config files");return}let s=(0,x.join)(D,u);if(!(0,bt.existsSync)(s)){this.logger.debug(`Config path not found: ${s}`);return}await this.copyer.copyPaths({sourcePath:s,targetPath:r,copyCallback:i})}generateTemplateDir(t){return this.copyer.copyPaths({sourcePath:(0,x.join)(this.context.options.templateRootPath,t.template),targetPath:t.targetPath})}async generateSubPackages(t){let{packagesNames:r="packages",subPackages:u=[],targetPath:i=""}=t,{templateRootPath:D}=this.context.options;for(let o of u){let s=(0,x.join)(D,o),a=(0,x.join)(i,r,o);this.logger.debug("copy sub package",s,a),await this.copyer.copyPaths({sourcePath:s,targetPath:a})}}};var At={name:"@qlover/create-app",version:"1.0.1",description:"Create a new app with a single command",private:!1,type:"module",files:["dist","package.json","README.md","CHANGELOG.md"],bin:{"create-app":"dist/index.js"},scripts:{lint:"eslint src --fix",build:"tsup","type-check":"tsc --noEmit","create:app":"node ./dist/index.js"},repository:{type:"git",url:"git+https://github.com/qlover/fe-base.git",directory:"packages/create-app"},homepage:"https://github.com/qlover/fe-base#readme",keywords:["create-app","fe-scripts","scripts"],author:"qlover",license:"ISC",publishConfig:{access:"public"},devDependencies:{"@qlover/logger":"workspace:*",ignore:"^7.0.3",lodash:"^4.17.21",ora:"^8.1.1"},dependencies:{"@qlover/scripts-context":"workspace:*",commander:"^13.1.0",inquirer:"^12.3.2"}};function Ul(){let e=new HD.Command;return e.version(At.version,"-v, --version","Show version").description(At.description).option("-d, --dry-run","Do not touch or write anything, but show the commands").option("-V, --verbose","Show more information").option("--config","Copy config files (default: true)",!0).option("--no-config","Do not copy config files"),e.parse(),e.opts()}async function YD(e=process.cwd()){let{dryRun:t,verbose:r,...u}=Ul(),i=(0,vt.resolve)(e,"./templates"),D=(0,vt.resolve)(e,"./configs");(0,xt.existsSync)(i)||(console.error("Template is empty!"),process.exit(1)),(0,xt.existsSync)(D)||(console.error("Configs is empty!"),process.exit(1)),await new ye({dryRun:t,verbose:r,options:{...u,templateRootPath:i,configsRootPath:D}}).generate()}YD(__dirname).catch(e=>{console.error(e),process.exit(1)});
|
package/dist/index.js
CHANGED
|
@@ -8,4 +8,4 @@ ${t}`,pD=Object.getOwnPropertyDescriptor(Function.prototype,"toString"),hD=Objec
|
|
|
8
8
|
`))this.#e+=Math.max(1,Math.ceil(Le(n,{countAnsiEscapeCodes:!0})/t))}get isEnabled(){return this.#a&&!this.#F}set isEnabled(t){if(typeof t!="boolean")throw new TypeError("The `isEnabled` option must be a boolean");this.#a=t}get isSilent(){return this.#F}set isSilent(t){if(typeof t!="boolean")throw new TypeError("The `isSilent` option must be a boolean");this.#F=t}frame(){let t=Date.now();(this.#i===-1||t-this.#c>=this.interval)&&(this.#i=++this.#i%this.#n.frames.length,this.#c=t);let{frames:r}=this.#n,u=r[this.#i];this.color&&(u=E[this.color](u));let i=typeof this.#s=="string"&&this.#s!==""?this.#s+" ":"",n=typeof this.text=="string"?" "+this.text:"",o=typeof this.#o=="string"&&this.#o!==""?" "+this.#o:"";return i+u+n+o}clear(){if(!this.#a||!this.#u.isTTY)return this;this.#u.cursorTo(0);for(let t=0;t<this.#D;t++)t>0&&this.#u.moveCursor(0,-1),this.#u.clearLine(1);return(this.#l||this.lastIndent!==this.#l)&&this.#u.cursorTo(this.#l),this.lastIndent=this.#l,this.#D=0,this}render(){return this.#F?this:(this.clear(),this.#u.write(this.frame()),this.#D=this.#e,this)}start(t){return t&&(this.text=t),this.#F?this:this.#a?this.isSpinning?this:(this.#t.hideCursor&&je.hide(this.#u),this.#t.discardStdin&&ce.stdin.isTTY&&(this.#r=!0,We.start()),this.render(),this.#f=setInterval(this.render.bind(this),this.interval),this):(this.text&&this.#u.write(`- ${this.text}
|
|
9
9
|
`),this)}stop(){return this.#a?(clearInterval(this.#f),this.#f=void 0,this.#i=0,this.clear(),this.#t.hideCursor&&je.show(this.#u),this.#t.discardStdin&&ce.stdin.isTTY&&this.#r&&(We.stop(),this.#r=!1),this):this}succeed(t){return this.stopAndPersist({symbol:k.success,text:t})}fail(t){return this.stopAndPersist({symbol:k.error,text:t})}warn(t){return this.stopAndPersist({symbol:k.warning,text:t})}info(t){return this.stopAndPersist({symbol:k.info,text:t})}stopAndPersist(t={}){if(this.#F)return this;let r=t.prefixText??this.#s,u=this.#E(r," "),i=t.symbol??" ",n=t.text??this.text,s=typeof n=="string"?(i?" ":"")+n:"",a=t.suffixText??this.#o,l=this.#g(a," "),p=u+i+s+l+`
|
|
10
10
|
`;return this.stop(),this.#u.write(p),this}};function zt(e){return new He(e)}async function Kt(e,t){let r=typeof e=="function",u=typeof e.then=="function";if(!r&&!u)throw new TypeError("Parameter `action` must be a Function or a Promise");let{successText:i,failText:n}=typeof t=="object"?t:{successText:void 0,failText:void 0},o=zt(t).start();try{let a=await(r?e(o):e);return o.succeed(i===void 0?void 0:typeof i=="string"?i:i(a)),a}catch(s){throw o.fail(n===void 0?void 0:typeof n=="string"?n:n(s)),s}}import{existsSync as Nn}from"fs";var Dr=ue(ir(),1);import{dirname as QD,join as Ze}from"path";import{existsSync as es,readFileSync as ts,promises as nr}from"fs";import{existsSync as JD,mkdirSync as ZD}from"fs";var H=class{static ensureDir(t){JD(t)||ZD(t,{recursive:!0})}};var{copyFile:rs,stat:us}=nr,Ce=class e{constructor(t,r=e.IGNORE_FILE){this.ignoreTargetPath=t;this.ignoreFile=r}static IGNORE_FILE=".gitignore.template";getIg(t=this.ignoreTargetPath){let r=Ze(t,this.ignoreFile);if(!es(r))return;let n=ts(r,"utf8").split(`
|
|
11
|
-
`).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#"));return(0,Dr.default)().add(n)}async copyFiles(t,r,u,i){let n=await nr.readdir(t);await Promise.all(n.map(async o=>{let s=Ze(t,o),a=Ze(r,o);if(u&&u.ignores(o))return;if(H.ensureDir(QD(a)),(await us(s)).isDirectory())await this.copyFiles(s,a,u,i);else{if(i&&await i(s,a))return;await rs(s,a)}}))}copyPaths({sourcePath:t,targetPath:r,copyCallback:u}){H.ensureDir(r);let i=this.getIg();return this.copyFiles(t,r,i,u)}};var jn=ue(In(),1);import{readFileSync as $l,writeFileSync as Ul,existsSync as Wl}from"fs";var _e=class{constructor(){}isJSONFilePath(t){return t.endsWith(".json")||t.endsWith(".json.template")}isTemplateFilePath(t){return t.endsWith(".template")}getRealTemplateFilePath(t){return t.replace(".template","")}readFile(t){return $l(t,"utf-8")}readJSONFile(t){return JSON.parse(this.readFile(t))}writeFile(t,r){Ul(this.getRealTemplateFilePath(t),r,{encoding:"utf-8"})}replaceFile(t,r){let u=this.readFile(t);return Object.keys(r).forEach(i=>{let n=r[i];u=u.replace(new RegExp(`\\[TPL:${i}\\]`,"g"),typeof n=="string"?n:JSON.stringify(n))}),u}mergeJSONFile(t,r){let u=this.readJSONFile(t),i=(0,jn.default)(r,u);this.writeFile(t,JSON.stringify(i,null,2))}composeConfigFile(t,r,u){if(this.isTemplateFilePath(r)){let i=this.replaceFile(r,t);if(this.isJSONFilePath(r)&&this.isJSONFilePath(u)){let n=this.getRealTemplateFilePath(u);return Wl(n)?(this.mergeJSONFile(n,JSON.parse(i)),!0):(this.writeFile(n,i),!0)}return this.writeFile(u,i),!0}return!1}};var Gn=["pack-app"],Be=class{ora;context;subPackages;copyer;compose;constructor(t){let r=t.options?.templateRootPath;if(!r)throw new Error("template path not exit");if(!Nn(r))throw new Error("template path not exit");this.ora=Kt,this.context=new Hl("create-app",t),this.subPackages=["node-lib","react-app","next-app"],this.copyer=new Ce(N(this.context.options.configsRootPath,"_common")),this.compose=new _e}get logger(){return this.context.logger}async steps(t){try{return await Yl.prompt(t)}catch(r){throw r.isTtyError,this.logger.error(r),r}}async action({label:t,task:r}){let u=r();u instanceof Promise||(u=Promise.resolve(u));let i=t;return this.ora(u,i),u}isPackageTemplate(t){return Gn.includes(t)}async getGeneratorContext(){let t=mt(this.subPackages,Gn),r=await this.steps(t);if(this.isPackageTemplate(r.template)){let u=_t(this.subPackages),i=await this.steps(u);Object.assign(r,i)}return r.targetPath=N(process.cwd(),r.projectName),r.releasePath=r.releasePath||"src",r}async generate(){let t=await this.getGeneratorContext();if(this.logger.debug("context is:",t,this.context.options.templateRootPath),t.subPackages){await this.action({label:"Generate Directories(subPackages)",task:async()=>{await this.generateTemplateDir(t),await this.generateSubPackages(t),await this.generateConfigs(t,t.targetPath,"_common")}});return}await this.action({label:"Generate Directory",task:async()=>{await this.generateTemplateDir(t),await this.generateConfigs(t,t.targetPath,"_common"),await this.generateConfigs(t,t.targetPath,t.template)}})}async generateConfigs(t,r,u){let i=(a,l)=>(this.logger.debug("copyCallback",a,l),this.compose.composeConfigFile(t,a,l)),{configsRootPath:n,config:o}=this.context.options;if(!o){this.logger.debug("no copy config files");return}let s=N(n,u);if(!Nn(s)){this.logger.debug(`Config path not found: ${s}`);return}await this.copyer.copyPaths({sourcePath:s,targetPath:r,copyCallback:i})}generateTemplateDir(t){return this.copyer.copyPaths({sourcePath:N(this.context.options.templateRootPath,t.template),targetPath:t.targetPath})}async generateSubPackages(t){let{packagesNames:r="packages",subPackages:u=[],targetPath:i=""}=t,{templateRootPath:n}=this.context.options;for(let o of u){let s=N(n,o),a=N(i,r,o);this.logger.debug("copy sub package",s,a),await this.copyer.copyPaths({sourcePath:s,targetPath:a})}}};var Et={name:"@qlover/create-app",version:"0.
|
|
11
|
+
`).map(o=>o.trim()).filter(o=>o&&!o.startsWith("#"));return(0,Dr.default)().add(n)}async copyFiles(t,r,u,i){let n=await nr.readdir(t);await Promise.all(n.map(async o=>{let s=Ze(t,o),a=Ze(r,o);if(u&&u.ignores(o))return;if(H.ensureDir(QD(a)),(await us(s)).isDirectory())await this.copyFiles(s,a,u,i);else{if(i&&await i(s,a))return;await rs(s,a)}}))}copyPaths({sourcePath:t,targetPath:r,copyCallback:u}){H.ensureDir(r);let i=this.getIg();return this.copyFiles(t,r,i,u)}};var jn=ue(In(),1);import{readFileSync as $l,writeFileSync as Ul,existsSync as Wl}from"fs";var _e=class{constructor(){}isJSONFilePath(t){return t.endsWith(".json")||t.endsWith(".json.template")}isTemplateFilePath(t){return t.endsWith(".template")}getRealTemplateFilePath(t){return t.replace(".template","")}readFile(t){return $l(t,"utf-8")}readJSONFile(t){return JSON.parse(this.readFile(t))}writeFile(t,r){Ul(this.getRealTemplateFilePath(t),r,{encoding:"utf-8"})}replaceFile(t,r){let u=this.readFile(t);return Object.keys(r).forEach(i=>{let n=r[i];u=u.replace(new RegExp(`\\[TPL:${i}\\]`,"g"),typeof n=="string"?n:JSON.stringify(n))}),u}mergeJSONFile(t,r){let u=this.readJSONFile(t),i=(0,jn.default)(r,u);this.writeFile(t,JSON.stringify(i,null,2))}composeConfigFile(t,r,u){if(this.isTemplateFilePath(r)){let i=this.replaceFile(r,t);if(this.isJSONFilePath(r)&&this.isJSONFilePath(u)){let n=this.getRealTemplateFilePath(u);return Wl(n)?(this.mergeJSONFile(n,JSON.parse(i)),!0):(this.writeFile(n,i),!0)}return this.writeFile(u,i),!0}return!1}};var Gn=["pack-app"],Be=class{ora;context;subPackages;copyer;compose;constructor(t){let r=t.options?.templateRootPath;if(!r)throw new Error("template path not exit");if(!Nn(r))throw new Error("template path not exit");this.ora=Kt,this.context=new Hl("create-app",t),this.subPackages=["node-lib","react-app","next-app"],this.copyer=new Ce(N(this.context.options.configsRootPath,"_common")),this.compose=new _e}get logger(){return this.context.logger}async steps(t){try{return await Yl.prompt(t)}catch(r){throw r.isTtyError,this.logger.error(r),r}}async action({label:t,task:r}){let u=r();u instanceof Promise||(u=Promise.resolve(u));let i=t;return this.ora(u,i),u}isPackageTemplate(t){return Gn.includes(t)}async getGeneratorContext(){let t=mt(this.subPackages,Gn),r=await this.steps(t);if(this.isPackageTemplate(r.template)){let u=_t(this.subPackages),i=await this.steps(u);Object.assign(r,i)}return r.targetPath=N(process.cwd(),r.projectName),r.releasePath=r.releasePath||"src",r}async generate(){let t=await this.getGeneratorContext();if(this.logger.debug("context is:",t,this.context.options.templateRootPath),t.subPackages){await this.action({label:"Generate Directories(subPackages)",task:async()=>{await this.generateTemplateDir(t),await this.generateSubPackages(t),await this.generateConfigs(t,t.targetPath,"_common")}});return}await this.action({label:"Generate Directory",task:async()=>{await this.generateTemplateDir(t),await this.generateConfigs(t,t.targetPath,"_common"),await this.generateConfigs(t,t.targetPath,t.template)}})}async generateConfigs(t,r,u){let i=(a,l)=>(this.logger.debug("copyCallback",a,l),this.compose.composeConfigFile(t,a,l)),{configsRootPath:n,config:o}=this.context.options;if(!o){this.logger.debug("no copy config files");return}let s=N(n,u);if(!Nn(s)){this.logger.debug(`Config path not found: ${s}`);return}await this.copyer.copyPaths({sourcePath:s,targetPath:r,copyCallback:i})}generateTemplateDir(t){return this.copyer.copyPaths({sourcePath:N(this.context.options.templateRootPath,t.template),targetPath:t.targetPath})}async generateSubPackages(t){let{packagesNames:r="packages",subPackages:u=[],targetPath:i=""}=t,{templateRootPath:n}=this.context.options;for(let o of u){let s=N(n,o),a=N(i,r,o);this.logger.debug("copy sub package",s,a),await this.copyer.copyPaths({sourcePath:s,targetPath:a})}}};var Et={name:"@qlover/create-app",version:"1.0.1",description:"Create a new app with a single command",private:!1,type:"module",files:["dist","package.json","README.md","CHANGELOG.md"],bin:{"create-app":"dist/index.js"},scripts:{lint:"eslint src --fix",build:"tsup","type-check":"tsc --noEmit","create:app":"node ./dist/index.js"},repository:{type:"git",url:"git+https://github.com/qlover/fe-base.git",directory:"packages/create-app"},homepage:"https://github.com/qlover/fe-base#readme",keywords:["create-app","fe-scripts","scripts"],author:"qlover",license:"ISC",publishConfig:{access:"public"},devDependencies:{"@qlover/logger":"workspace:*",ignore:"^7.0.3",lodash:"^4.17.21",ora:"^8.1.1"},dependencies:{"@qlover/scripts-context":"workspace:*",commander:"^13.1.0",inquirer:"^12.3.2"}};function Kl(){let e=new zl;return e.version(Et.version,"-v, --version","Show version").description(Et.description).option("-d, --dry-run","Do not touch or write anything, but show the commands").option("-V, --verbose","Show more information").option("--config","Copy config files (default: true)",!0).option("--no-config","Do not copy config files"),e.parse(),e.opts()}async function kn(e=process.cwd()){let{dryRun:t,verbose:r,...u}=Kl(),i=Mn(e,"./templates"),n=Mn(e,"./configs");Ln(i)||(console.error("Template is empty!"),process.exit(1)),Ln(n)||(console.error("Configs is empty!"),process.exit(1)),await new Be({dryRun:t,verbose:r,options:{...u,templateRootPath:i,configsRootPath:n}}).generate()}import{fileURLToPath as Xl}from"url";import{dirname as Jl}from"path";var Zl=Xl(import.meta.url),Ql=Jl(Zl);kn(Ql).catch(e=>{console.error(e),process.exit(1)});
|
|
@@ -11,9 +11,10 @@ generateLocales().catch((error) => {
|
|
|
11
11
|
|
|
12
12
|
const nextConfig: NextConfig = {
|
|
13
13
|
// reactStrictMode: false,
|
|
14
|
-
turbopack:
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
// turbopack 在接下本地 file: 依赖时支持还不够好
|
|
15
|
+
// turbopack: {
|
|
16
|
+
// root: __dirname // 明确指定根目录
|
|
17
|
+
// },
|
|
17
18
|
transpilePackages: ['@qlover/corekit-bridge', '@qlover/fe-corekit'],
|
|
18
19
|
env: {
|
|
19
20
|
APP_ENV: process.env.APP_ENV
|
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"scripts": {
|
|
6
|
-
"dev": "cross-env APP_ENV=localhost next dev --
|
|
7
|
-
"dev:staging": "cross-env APP_ENV=staging next dev --
|
|
8
|
-
"dev:prod": "cross-env APP_ENV=production next dev --
|
|
9
|
-
"
|
|
10
|
-
"build
|
|
11
|
-
"build:
|
|
6
|
+
"dev": "cross-env APP_ENV=localhost next dev --port 3100",
|
|
7
|
+
"dev:staging": "cross-env APP_ENV=staging next dev --port 3100",
|
|
8
|
+
"dev:prod": "cross-env APP_ENV=production next dev --port 3100",
|
|
9
|
+
"dev:turbo": "cross-env APP_ENV=localhost next dev --turbopack --port 3100",
|
|
10
|
+
"build": "cross-env APP_ENV=localhost next build",
|
|
11
|
+
"build:staging": "cross-env APP_ENV=staging next build",
|
|
12
|
+
"build:prod": "cross-env APP_ENV=production next build",
|
|
12
13
|
"start": "next start --port 3101",
|
|
13
|
-
"lint": "
|
|
14
|
-
"lint:fix": "
|
|
14
|
+
"lint": "npm run type-check && eslint ./src ./config ./make ./migrations",
|
|
15
|
+
"lint:fix": "npm run type-check && eslint ./src ./config ./make ./migrations --ext .ts,.tsx --fix",
|
|
15
16
|
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
16
17
|
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,scss,md}\"",
|
|
17
|
-
"fix": "npm run lint:fix && npm run format"
|
|
18
|
+
"fix": "npm run lint:fix && npm run format",
|
|
19
|
+
"type-check": "tsc --build --force"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"@ant-design/icons": "^6.0.0",
|
|
@@ -26,6 +28,7 @@
|
|
|
26
28
|
"@brain-toolkit/react-kit": "^0.1.0",
|
|
27
29
|
"@qlover/corekit-bridge": "latest",
|
|
28
30
|
"@qlover/fe-corekit": "latest",
|
|
31
|
+
"@qlover/logger": "latest",
|
|
29
32
|
"@qlover/slice-store-react": "^1.4.1",
|
|
30
33
|
"@supabase/postgrest-js": "^2.87.1",
|
|
31
34
|
"@supabase/ssr": "^0.7.0",
|
|
@@ -19,7 +19,6 @@ export function LoginForm(props: { tt: LoginI18nInterface }) {
|
|
|
19
19
|
const { tt } = props;
|
|
20
20
|
const t = useWarnTranslations();
|
|
21
21
|
const userService = useIOC(I.UserServiceInterface);
|
|
22
|
-
const logger = useIOC(I.Logger);
|
|
23
22
|
const appConfig = useIOC(I.AppConfig);
|
|
24
23
|
const routerService = useIOC(I.RouterServiceInterface);
|
|
25
24
|
const [loading, setLoading] = useState(false);
|
|
@@ -29,8 +28,8 @@ export function LoginForm(props: { tt: LoginI18nInterface }) {
|
|
|
29
28
|
setLoading(true);
|
|
30
29
|
await userService.login(values);
|
|
31
30
|
routerService.replaceHome();
|
|
32
|
-
} catch
|
|
33
|
-
|
|
31
|
+
} catch {
|
|
32
|
+
// do nothing
|
|
34
33
|
} finally {
|
|
35
34
|
setLoading(false);
|
|
36
35
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ExecutorContextInterface,
|
|
2
3
|
ExecutorError,
|
|
3
|
-
|
|
4
|
-
type ExecutorPlugin
|
|
4
|
+
LifecyclePluginInterface
|
|
5
5
|
} from '@qlover/fe-corekit';
|
|
6
6
|
import { inject, injectable } from 'inversify';
|
|
7
7
|
import { i18nKeySchema } from '@config/i18n/i18nKeyScheam';
|
|
@@ -13,7 +13,9 @@ import type { I18nServiceInterface } from '../port/I18nServiceInterface';
|
|
|
13
13
|
import type { UIDialogInterface } from '@qlover/corekit-bridge';
|
|
14
14
|
|
|
15
15
|
@injectable()
|
|
16
|
-
export class DialogErrorPlugin
|
|
16
|
+
export class DialogErrorPlugin
|
|
17
|
+
implements LifecyclePluginInterface<ExecutorContextInterface<unknown>>
|
|
18
|
+
{
|
|
17
19
|
public readonly pluginName = 'DialogErrorPlugin';
|
|
18
20
|
|
|
19
21
|
constructor(
|
|
@@ -27,7 +29,7 @@ export class DialogErrorPlugin implements ExecutorPlugin {
|
|
|
27
29
|
/**
|
|
28
30
|
* @override
|
|
29
31
|
*/
|
|
30
|
-
public onError(context:
|
|
32
|
+
public onError(context: ExecutorContextInterface<unknown>): void {
|
|
31
33
|
const { error, hooksRuntimes } = context;
|
|
32
34
|
const runtimesError = hooksRuntimes.returnValue;
|
|
33
35
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { clone, isObject } from 'lodash';
|
|
2
2
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
ExecutorContextInterface,
|
|
4
|
+
LifecyclePluginInterface,
|
|
5
|
+
RequestAdapterConfig,
|
|
6
|
+
EncryptorInterface
|
|
7
7
|
} from '@qlover/fe-corekit';
|
|
8
8
|
|
|
9
|
-
export interface RequestEncryptPluginProps<
|
|
10
|
-
Request
|
|
11
|
-
> extends RequestAdapterConfig<Request> {
|
|
9
|
+
export interface RequestEncryptPluginProps<Request = unknown>
|
|
10
|
+
extends RequestAdapterConfig<Request> {
|
|
12
11
|
/**
|
|
13
12
|
* 加密密码在 HTTP 请求中
|
|
14
13
|
*
|
|
@@ -19,16 +18,21 @@ export interface RequestEncryptPluginProps<
|
|
|
19
18
|
encryptProps?: string[] | string;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
export class RequestEncryptPlugin
|
|
21
|
+
export class RequestEncryptPlugin
|
|
22
|
+
implements
|
|
23
|
+
LifecyclePluginInterface<
|
|
24
|
+
ExecutorContextInterface<RequestEncryptPluginProps>
|
|
25
|
+
>
|
|
26
|
+
{
|
|
23
27
|
public readonly pluginName = 'RequestEncryptPlugin';
|
|
24
28
|
|
|
25
|
-
constructor(protected encryptor:
|
|
29
|
+
constructor(protected encryptor: EncryptorInterface<string, string>) {}
|
|
26
30
|
|
|
27
31
|
/**
|
|
28
32
|
* @override
|
|
29
33
|
*/
|
|
30
34
|
public onBefore(
|
|
31
|
-
context:
|
|
35
|
+
context: ExecutorContextInterface<RequestEncryptPluginProps>
|
|
32
36
|
): void | Promise<void> {
|
|
33
37
|
const { responseType, encryptProps } = context.parameters;
|
|
34
38
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Base64Serializer, type
|
|
1
|
+
import { Base64Serializer, type EncryptorInterface } from '@qlover/fe-corekit';
|
|
2
2
|
import { inject, injectable } from 'inversify';
|
|
3
3
|
import { I } from '@config/IOCIdentifier';
|
|
4
4
|
import type { AppConfig } from './AppConfig';
|
|
5
5
|
|
|
6
6
|
@injectable()
|
|
7
|
-
export class StringEncryptor implements
|
|
7
|
+
export class StringEncryptor implements EncryptorInterface<string, string> {
|
|
8
8
|
private readonly key;
|
|
9
9
|
|
|
10
10
|
constructor(
|
|
@@ -13,10 +13,7 @@ export class I18nServiceState implements StoreStateInterface {
|
|
|
13
13
|
public loading: boolean = false;
|
|
14
14
|
constructor(public language: I18nServiceLocale) {}
|
|
15
15
|
}
|
|
16
|
-
export abstract class I18nServiceInterface
|
|
17
|
-
extends StoreInterface<I18nServiceState>
|
|
18
|
-
implements I18nServiceInterface
|
|
19
|
-
{
|
|
16
|
+
export abstract class I18nServiceInterface extends StoreInterface<I18nServiceState> {
|
|
20
17
|
/**
|
|
21
18
|
* @override
|
|
22
19
|
*/
|
|
@@ -5,10 +5,14 @@ import {
|
|
|
5
5
|
} from '../port/I18nServiceInterface';
|
|
6
6
|
import type { I18nServiceLocale } from '../port/I18nServiceInterface';
|
|
7
7
|
import type { useTranslations } from 'next-intl';
|
|
8
|
+
import { BootstrapExecutorPlugin } from '@qlover/corekit-bridge';
|
|
8
9
|
|
|
9
10
|
type TranslationFunction = ReturnType<typeof useTranslations>;
|
|
10
11
|
|
|
11
|
-
export class I18nService
|
|
12
|
+
export class I18nService
|
|
13
|
+
extends I18nServiceInterface
|
|
14
|
+
implements BootstrapExecutorPlugin
|
|
15
|
+
{
|
|
12
16
|
public readonly pluginName = 'I18nService';
|
|
13
17
|
protected pathname: string = '';
|
|
14
18
|
protected translator: TranslationFunction | null = null;
|
|
@@ -34,7 +38,7 @@ export class I18nService extends I18nServiceInterface {
|
|
|
34
38
|
/**
|
|
35
39
|
* @override
|
|
36
40
|
*/
|
|
37
|
-
public
|
|
41
|
+
public onBefore(): void {}
|
|
38
42
|
|
|
39
43
|
public override async changeLanguage(
|
|
40
44
|
language: I18nServiceLocale
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
ExecutorContextInterface,
|
|
3
3
|
RequestAdapterFetch,
|
|
4
|
-
|
|
4
|
+
RequestExecutor
|
|
5
5
|
} from '@qlover/fe-corekit';
|
|
6
|
-
import {
|
|
6
|
+
import { injectable } from 'inversify';
|
|
7
7
|
import type { AppApiConfig } from '../appApi/AppApiRequester';
|
|
8
8
|
|
|
9
|
+
export interface AdminApiRequesterContext
|
|
10
|
+
extends ExecutorContextInterface<AppApiConfig> {}
|
|
11
|
+
|
|
9
12
|
@injectable()
|
|
10
|
-
export class AdminApiRequester extends
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
export class AdminApiRequester extends RequestExecutor<
|
|
14
|
+
AppApiConfig,
|
|
15
|
+
AdminApiRequesterContext
|
|
16
|
+
> {
|
|
17
|
+
constructor() {
|
|
14
18
|
super(
|
|
15
19
|
new RequestAdapterFetch({
|
|
16
20
|
baseURL: '/api/admin',
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
type AppApiTransaction
|
|
9
9
|
} from '../appApi/AppApiRequester';
|
|
10
10
|
import type { ResourceInterface, ResourceQuery } from '@qlover/corekit-bridge';
|
|
11
|
-
import
|
|
11
|
+
import { RequestExecutor } from '@qlover/fe-corekit';
|
|
12
|
+
import { AdminApiRequesterContext } from './AdminApiRequester';
|
|
12
13
|
|
|
13
14
|
export type AdminLocalesListTransaction = AppApiTransaction<
|
|
14
15
|
ResourceQuery,
|
|
@@ -24,17 +25,17 @@ export type AdminLocalesUpdateTransaction = AppApiTransaction<
|
|
|
24
25
|
export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
25
26
|
constructor(
|
|
26
27
|
@inject(AppApiRequester)
|
|
27
|
-
protected client:
|
|
28
|
+
protected client: RequestExecutor<AppApiConfig, AdminApiRequesterContext>
|
|
28
29
|
) {}
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* @override
|
|
32
33
|
*/
|
|
33
34
|
public create(data: LocalesSchema): Promise<unknown> {
|
|
34
|
-
return this.client.request
|
|
35
|
+
return this.client.request({
|
|
35
36
|
url: '/admin/locales/create',
|
|
36
37
|
method: 'POST',
|
|
37
|
-
data: data
|
|
38
|
+
data: data
|
|
38
39
|
});
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -42,10 +43,10 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
42
43
|
* @override
|
|
43
44
|
*/
|
|
44
45
|
public remove(data: Partial<LocalesSchema>): Promise<unknown> {
|
|
45
|
-
return this.client.request
|
|
46
|
+
return this.client.request({
|
|
46
47
|
url: '/admin/locales',
|
|
47
48
|
method: 'DELETE',
|
|
48
|
-
data
|
|
49
|
+
data
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -55,7 +56,7 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
55
56
|
public search(
|
|
56
57
|
params: ResourceQuery
|
|
57
58
|
): Promise<AdminLocalesListTransaction['response']> {
|
|
58
|
-
return this.client.request
|
|
59
|
+
return this.client.request({
|
|
59
60
|
url: '/admin/locales',
|
|
60
61
|
method: 'GET',
|
|
61
62
|
params: params as unknown as Record<string, unknown>
|
|
@@ -66,10 +67,10 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
66
67
|
* @override
|
|
67
68
|
*/
|
|
68
69
|
public export(data: LocalesSchema): Promise<unknown> {
|
|
69
|
-
return this.client.request
|
|
70
|
+
return this.client.request({
|
|
70
71
|
url: '/admin/locales',
|
|
71
72
|
method: 'GET',
|
|
72
|
-
data
|
|
73
|
+
data
|
|
73
74
|
});
|
|
74
75
|
}
|
|
75
76
|
|
|
@@ -79,7 +80,7 @@ export class AdminLocalesApi implements ResourceInterface<LocalesSchema> {
|
|
|
79
80
|
public update(
|
|
80
81
|
data: Partial<LocalesSchema>
|
|
81
82
|
): Promise<AdminLocalesUpdateTransaction['response']> {
|
|
82
|
-
return this.client.request
|
|
83
|
+
return this.client.request({
|
|
83
84
|
url: `/admin/locales/update`,
|
|
84
85
|
method: 'POST',
|
|
85
86
|
data
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
type AppApiTransaction
|
|
8
8
|
} from '../appApi/AppApiRequester';
|
|
9
9
|
import type { ResourceInterface, ResourceQuery } from '@qlover/corekit-bridge';
|
|
10
|
-
import
|
|
10
|
+
import { RequestExecutor } from '@qlover/fe-corekit';
|
|
11
|
+
import { AdminApiRequesterContext } from './AdminApiRequester';
|
|
11
12
|
|
|
12
13
|
export type AdminUserListTransaction = AppApiTransaction<
|
|
13
14
|
ResourceQuery,
|
|
@@ -18,7 +19,7 @@ export type AdminUserListTransaction = AppApiTransaction<
|
|
|
18
19
|
export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
19
20
|
constructor(
|
|
20
21
|
@inject(AppApiRequester)
|
|
21
|
-
protected client:
|
|
22
|
+
protected client: RequestExecutor<AppApiConfig, AdminApiRequesterContext>
|
|
22
23
|
) {}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -27,10 +28,13 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
27
28
|
public async search(
|
|
28
29
|
params: AdminUserListTransaction['request']
|
|
29
30
|
): Promise<AdminUserListTransaction['response']> {
|
|
30
|
-
const response = await this.client.request<
|
|
31
|
+
const response = await this.client.request<
|
|
32
|
+
AdminUserListTransaction['response'],
|
|
33
|
+
AdminUserListTransaction['request']
|
|
34
|
+
>({
|
|
31
35
|
url: '/admin/users',
|
|
32
36
|
method: 'GET',
|
|
33
|
-
params
|
|
37
|
+
params
|
|
34
38
|
});
|
|
35
39
|
|
|
36
40
|
return response;
|
|
@@ -40,10 +44,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
40
44
|
* @override
|
|
41
45
|
*/
|
|
42
46
|
public create(data: UserSchema): Promise<unknown> {
|
|
43
|
-
return this.client.request
|
|
47
|
+
return this.client.request({
|
|
44
48
|
url: '/admin/users',
|
|
45
49
|
method: 'POST',
|
|
46
|
-
data
|
|
50
|
+
data
|
|
47
51
|
});
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -51,10 +55,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
51
55
|
* @override
|
|
52
56
|
*/
|
|
53
57
|
public remove(data: UserSchema): Promise<unknown> {
|
|
54
|
-
return this.client.request
|
|
58
|
+
return this.client.request({
|
|
55
59
|
url: '/admin/users',
|
|
56
60
|
method: 'DELETE',
|
|
57
|
-
data
|
|
61
|
+
data
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
|
|
@@ -62,10 +66,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
62
66
|
* @override
|
|
63
67
|
*/
|
|
64
68
|
public update(data: UserSchema): Promise<unknown> {
|
|
65
|
-
return this.client.request
|
|
69
|
+
return this.client.request({
|
|
66
70
|
url: '/admin/users',
|
|
67
71
|
method: 'PUT',
|
|
68
|
-
data
|
|
72
|
+
data
|
|
69
73
|
});
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -73,10 +77,10 @@ export class AdminUserApi implements ResourceInterface<UserSchema> {
|
|
|
73
77
|
* @override
|
|
74
78
|
*/
|
|
75
79
|
public export(data: UserSchema): Promise<unknown> {
|
|
76
|
-
return this.client.request
|
|
80
|
+
return this.client.request({
|
|
77
81
|
url: '/admin/users',
|
|
78
82
|
method: 'GET',
|
|
79
|
-
data
|
|
83
|
+
data
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
86
|
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ExecutorContextInterface,
|
|
2
3
|
ExecutorError,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type ExecutorPlugin
|
|
4
|
+
isRequestAdapterResponse,
|
|
5
|
+
LifecyclePluginInterface
|
|
6
6
|
} from '@qlover/fe-corekit';
|
|
7
7
|
import type { AppApiErrorInterface } from '@/base/port/AppApiInterface';
|
|
8
8
|
import type { AppApiConfig } from './AppApiRequester';
|
|
9
9
|
import type { LoggerInterface } from '@qlover/logger';
|
|
10
10
|
|
|
11
|
-
export class AppApiPlugin implements
|
|
11
|
+
export class AppApiPlugin implements LifecyclePluginInterface<
|
|
12
|
+
ExecutorContextInterface<AppApiConfig>
|
|
13
|
+
> {
|
|
12
14
|
public readonly pluginName = 'AppApiPlugin';
|
|
13
15
|
|
|
14
16
|
constructor(protected logger: LoggerInterface) {}
|
|
@@ -30,48 +32,46 @@ export class AppApiPlugin implements ExecutorPlugin {
|
|
|
30
32
|
/**
|
|
31
33
|
* @override
|
|
32
34
|
*/
|
|
33
|
-
public onSuccess(
|
|
34
|
-
context: ExecutorContext<AppApiConfig>
|
|
35
|
-
): void | Promise<void> {
|
|
35
|
+
public onSuccess(context: ExecutorContextInterface<AppApiConfig>): void {
|
|
36
36
|
const response = context.returnValue;
|
|
37
37
|
const { parameters } = context;
|
|
38
38
|
|
|
39
|
+
// Important: 当响应数据失败则抛出错误
|
|
40
|
+
if (isRequestAdapterResponse(response)) {
|
|
41
|
+
if (this.isAppApiErrorInterface(response.data)) {
|
|
42
|
+
throw new ExecutorError(response.data.message || response.data.id, response);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
39
46
|
this.logger.info(
|
|
40
47
|
`%c[AppApi ${parameters.method} ${parameters.url}]%c - ${new Date().toLocaleString()}`,
|
|
41
48
|
'color: #0f0;',
|
|
42
49
|
'color: inherit;',
|
|
43
50
|
response
|
|
44
51
|
);
|
|
45
|
-
|
|
46
|
-
if (this.isAppApiErrorInterface(response)) {
|
|
47
|
-
throw new Error(response.message || response.id);
|
|
48
|
-
}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* @override
|
|
53
56
|
*/
|
|
54
57
|
public async onError(
|
|
55
|
-
context:
|
|
58
|
+
context: ExecutorContextInterface<AppApiConfig>
|
|
56
59
|
): Promise<ExecutorError | void> {
|
|
57
60
|
const { error, parameters } = context;
|
|
58
61
|
|
|
59
62
|
this.loggerError(parameters, error);
|
|
60
63
|
|
|
61
|
-
if (error instanceof
|
|
62
|
-
|
|
63
|
-
let response = error?.response;
|
|
64
|
+
if (error instanceof Error && parameters.responseType === 'json') {
|
|
65
|
+
let response = error?.cause;
|
|
64
66
|
|
|
65
67
|
if (response instanceof Response) {
|
|
66
68
|
// clone the response to avoid mutating the original response
|
|
67
69
|
response = response.clone();
|
|
68
70
|
|
|
69
|
-
const json = await this.getResponseJson(response);
|
|
71
|
+
const json = await this.getResponseJson(response as Response);
|
|
70
72
|
|
|
71
73
|
if (this.isAppApiErrorInterface(json)) {
|
|
72
|
-
|
|
73
|
-
// context.error = newError;
|
|
74
|
-
return newError;
|
|
74
|
+
return new ExecutorError(json.id, json);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
}
|
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
RequestAdapterFetch,
|
|
4
|
-
RequestTransaction
|
|
5
|
-
} from '@qlover/fe-corekit';
|
|
6
|
-
import { inject, injectable } from 'inversify';
|
|
1
|
+
import { LifecycleExecutor, RequestAdapterFetch, RequestExecutor } from '@qlover/fe-corekit';
|
|
2
|
+
import { injectable } from 'inversify';
|
|
7
3
|
import type { RequestEncryptPluginProps } from '@/base/cases/RequestEncryptPlugin';
|
|
8
4
|
import type { AppApiResult } from '@/base/port/AppApiInterface';
|
|
9
5
|
import type {
|
|
6
|
+
ExecutorContextInterface,
|
|
10
7
|
RequestAdapterConfig,
|
|
11
|
-
RequestAdapterResponse
|
|
12
|
-
RequestTransactionInterface
|
|
8
|
+
RequestAdapterResponse
|
|
13
9
|
} from '@qlover/fe-corekit';
|
|
14
10
|
|
|
11
|
+
export interface RequestTransactionInterface<Request, Response> {
|
|
12
|
+
request: Request;
|
|
13
|
+
response: Response;
|
|
14
|
+
}
|
|
15
|
+
|
|
15
16
|
export interface AppApiConfig<Request = unknown>
|
|
16
|
-
extends RequestAdapterConfig<Request>,
|
|
17
|
+
extends RequestAdapterConfig<Request>,
|
|
18
|
+
RequestEncryptPluginProps<Request> {}
|
|
19
|
+
|
|
20
|
+
export interface AppApiRequesterContext
|
|
21
|
+
extends ExecutorContextInterface<AppApiConfig> {}
|
|
17
22
|
|
|
18
23
|
/**
|
|
19
24
|
* UserApiResponse
|
|
@@ -32,26 +37,26 @@ export type AppApiResponse<
|
|
|
32
37
|
/**
|
|
33
38
|
* UserApi common transaction
|
|
34
39
|
*/
|
|
35
|
-
export interface AppApiTransaction<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
>
|
|
39
|
-
|
|
40
|
-
AppApiResponse<Request, Response>
|
|
41
|
-
> {
|
|
40
|
+
export interface AppApiTransaction<Request = unknown, Response = unknown>
|
|
41
|
+
extends RequestTransactionInterface<
|
|
42
|
+
AppApiConfig<Request>,
|
|
43
|
+
AppApiResponse<Request, Response>
|
|
44
|
+
> {
|
|
42
45
|
data: AppApiConfig<Request>['data'];
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
@injectable()
|
|
46
|
-
export class AppApiRequester extends
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
export class AppApiRequester extends RequestExecutor<
|
|
50
|
+
AppApiConfig,
|
|
51
|
+
AppApiRequesterContext
|
|
52
|
+
> {
|
|
53
|
+
constructor() {
|
|
50
54
|
super(
|
|
51
55
|
new RequestAdapterFetch({
|
|
52
56
|
baseURL: '/api',
|
|
53
57
|
responseType: 'json'
|
|
54
|
-
})
|
|
58
|
+
}),
|
|
59
|
+
new LifecycleExecutor()
|
|
55
60
|
);
|
|
56
61
|
}
|
|
57
62
|
}
|