neo-cmp-cli 1.9.7 → 1.9.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/index2.js +1 -1
  2. package/dist/main2.js +1 -1
  3. package/dist/neo/deleteCmp.js +1 -1
  4. package/dist/neo/neoLogin.js +1 -1
  5. package/dist/neo/neoService.js +1 -1
  6. package/dist/neo/pullCmp.js +1 -1
  7. package/dist/neo/pushCmp.js +1 -1
  8. package/dist/oss/publish2oss.js +1 -1
  9. package/dist/package.json.js +1 -1
  10. package/dist/plugins/AddNeoRequirePlugin.js +1 -1
  11. package/dist/utils/autoEntryRootDir.js +1 -1
  12. package/dist/utils/cmpUtils/createCmpByZip.js +1 -1
  13. package/dist/utils/projectNameValidator.js +1 -1
  14. package/dist/utils/projectUtils/createCmpProjectZip.js +1 -1
  15. package/dist/utils/replaceInPackage.js +1 -1
  16. package/dist/utils/resetPackageVersion.js +1 -1
  17. package/package.json +2 -2
  18. package/template/develop/comTree/347/224/237/346/210/220/350/277/207/347/250/213/345/210/206/346/236/220.md +469 -0
  19. package/template/empty-custom-cmp-template/package.json +3 -1
  20. package/template/neo-custom-cmp-template/@types/neo-ui-common.d.ts +36 -0
  21. package/template/neo-custom-cmp-template/src/components/entityCardList/index.tsx +13 -5
  22. package/template/neo-custom-cmp-template/src/components/entityCardList/model.ts +0 -1
  23. package/template/neo-custom-cmp-template/src/components/entityForm_c/index.tsx +3 -3
  24. package/template/neo-custom-cmp-template/src/components/entityForm_c/model.ts +2 -3
  25. package/template/neo-custom-cmp-template/src/components/entityTable/index.tsx +6 -1
  26. package/template/neo-custom-cmp-template/src/components/entityTable/model.ts +22 -0
  27. package/test/deprecate-versions.js +1 -1
package/dist/index2.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./_virtual/index.js"),s=require("figlet"),o=require("yargs"),a=require("chalk"),t=require("inquirer"),n=require("ora"),p=require("./main2.js"),i=require("./package.json.js");var c;exports.__require=function(){if(c)return e.__exports;c=1;const m=s,r=o,l=a,u=t,d=n,{neoInit:g,neoInitByCopy:h,inspect:y,neoConfigInit:b,validateProjectName:C,getCmpTypeByDir:v,NeoService:f,NeoLoginService:$,hasNeoProject:x,consoleTag:T,errorLog:U,successLog:j}=p.__require(),w=p.__require(),q=i.default,N=w.projectConfig,_=function(e){return l.green(l.bold(e))},M=m.textSync("neo",{font:"Lean"});return console.log(l.green(M)),console.log(l.green(`当前版本:v${q.version}.\n`)),r.command("init [options]","根据模板创建一个自定义组件",e=>{e.reset().usage(_("Usage")+": $0 init [options]").option("type",{alias:"t",describe:"自定义组件类型(react ts 技术栈/ vue2.0 技术栈/ react 技术栈)"}).option("name",{alias:"n",describe:"自定义组件项目名称"}).alias("h","help")},e=>{if(e.type&&e.name)x()&&(U(`${T}创建自定义组件失败,当前目录(${process.cwd()})已经是一个自定义组件项目,请勿重复创建。`),process.exit(1)),"github"===e.mode?g(e.type,e.name):h(e.type,e.name);else{const s=[],o=[{name:"react&ts 自定义组件",value:"react-ts",short:"react-ts"},{name:"Neo 自定义组件(使用平台实体数据源)",value:"neo",short:"neo"},{name:"antd 自定义组件",value:"antd",short:"antd"},{name:"echarts 自定义组件",value:"echarts",short:"echarts"},{name:"vue2 自定义组件",value:"vue2",short:"vue2"}];e.type||s.push({name:"type",type:"list",message:"请选择您要创建的自定义组件类型: ",default:"react-ts",choices:o}),e.name||s.push({name:"name",type:"input",message:"请设置自定义组件项目名称(默认 neoCustomCmp):",default:"neoCustomCmp"}),u.prompt(s).then(s=>{const{isValid:o,errors:a}=C(s.name);o||(U(a.join("\n")),process.exit(1)),"github"===e.mode?g(s.type,s.name):h(s.type,s.name)})}}).command("config init","创建 neo.config.js 配置文件",e=>{e.reset().usage(_("Usage")+": $0 config init").alias("h","help")},()=>{b("neo.config.js")}).command("login","登录 NeoCRM 平台(OAuth2 授权)",e=>{e.reset().usage(_("Usage")+": $0 login").alias("h","help")},async()=>{try{const e=new $(N.neoConfig);await e.login(),process.exit(0)}catch(e){U(`\n登录失败: ${e.message}`),process.exit(1)}}).command("logout","登出 NeoCRM 平台",e=>{e.reset().usage(_("Usage")+": $0 logout").alias("h","help")},async()=>{try{const e=new $(N.neoConfig);await e.logout(),process.exit(0)}catch(e){U(`\n登出失败: ${e.message}`),process.exit(1)}}).command("create","创建项目或者组件",e=>e.command("project [options]","创建自定义组件项目(含工程代码)",e=>{e.reset().usage(_("Usage")+": $0 project [options]").option("name",{alias:"n",describe:"自定义组件项目名称"}).alias("h","help")},e=>{if(e.name)w.createCmpProjectByTemplate(e.name);else{const e=[{name:"name",type:"input",message:"请设置自定义组件项目名称:"}];u.prompt(e).then(e=>{const{isValid:s,errors:o}=C(e.name);s||(U(o.join("\n")),process.exit(1)),e.name?w.createCmpProjectByTemplate(e.name):(U("自定义组件项目名称不能为空。"),process.exit(1))})}}).command("cmp [options]","创建自定义组件",e=>{e.reset().usage(_("Usage")+": $0 cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.createCmpByTemplate(e.name);else{const e=[{name:"name",type:"input",message:"请设置自定义组件名称:"}];u.prompt(e).then(e=>{e.name?w.createCmpByTemplate(e.name):(U("自定义组件名称不能为空。"),process.exit(1))})}})).command("pull cmp [options]","拉取线上自定义组件",e=>{e.reset().usage(_("Usage")+": $0 pull cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},async e=>{if(e.name)w.pullCmp(e.name);else{const e=new f(N.neoConfig),s=d("正在拉取线上自定义组件列表...").start(),o=await e.getCustomCmpList();0===o.length&&(U("当前租户暂无任何自定义组件。"),process.exit(1)),s.stop("线上自定义组件列表拉取成功。");const a=[{name:"cmpType",type:"list",message:"请选择要拉取的自定义组件:",choices:o.map(e=>({name:`${e.label}(${e.cmpType})`,value:e.cmpType}))}];u.prompt(a).then(s=>{s.cmpType?w.pullCmp(s.cmpType,e):(U("自定义组件名称不能为空。"),process.exit(1))})}}).command("delete cmp [options]","删除线上自定义组件",e=>{e.reset().usage(_("Usage")+": $0 delete cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},async e=>{if(e.name)w.deleteCmp(e.name);else{const e=new f(N.neoConfig),s=d("正在获取线上自定义组件列表...").start(),o=await e.getCustomCmpList();0===o.length&&(U("当前租户暂无任何自定义组件。"),process.exit(1)),s.stop("线上自定义组件列表获取成功。");const a=[{name:"cmpType",type:"list",message:"请选择要删除的自定义组件:",choices:o.map(e=>({name:`${e.label}(${e.cmpType})`,value:e.cmpType}))}];u.prompt(a).then(s=>{s.cmpType?w.deleteCmp(s.cmpType,e):(U("自定义组件名称不能为空。"),process.exit(1))})}}).command("preview [options]","预览指定自定义组件(仅预览组件本身内容)",e=>{e.reset().usage(_("Usage")+": $0 preview [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.previewCmp(e.name);else{const e=v();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要预览的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要预览的自定义组件。"),process.exit(1)),w.previewCmp(e.cmpType)})}}).command("dev","开启本地调试模式",e=>{e.reset().usage(_("Usage")+": $0 dev").alias("h","help")},()=>{w.dev()}).command("linkDebug","开启外链调试模式(在线上页面设计器端调试)",e=>{e.reset().usage(_("Usage")+": $0 linkDebug").alias("h","help")},e=>{w.linkDebug()}).command("build","构建生产环境代码",e=>{e.reset().usage(_("Usage")+": $0 build").alias("h","help")},e=>{w.build()}).command("build2lib","构建 UMD 模块",e=>{e.reset().usage(_("Usage")+": $0 build2lib").alias("h","help")},e=>{w.build2lib()}).command("publish2oss [options]","发布到oss",e=>{e.reset().usage(_("Usage")+": $0 publish2oss [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.publish2oss(e.name);else{const e=v();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要发布的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要发布的自定义组件。"),process.exit(1)),w.publish2oss(e.cmpType)})}}).command("push cmp [options]","构建并发布自定义组件到 NeoCRM 平台",e=>{e.reset().usage(_("Usage")+": $0 push cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.pushCmp(e.name);else{const e=v();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要发布的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要发布的自定义组件。"),process.exit(1)),w.pushCmp(e.cmpType)})}}).command("build2esm","构建 ESM 模块",e=>{e.reset().usage(_("Usage")+": $0 build2esm").alias("h","help")},()=>{w.build2esm()}).command("inspect","输出当前配置文件",e=>{e.reset().usage(_("Usage")+": $0 inspect").option("type",{alias:"t",describe:"环境类型(本地调试环境/生产环境/library构建环境)",default:"build"}).alias("h","help")},e=>{y(e.type)}).command("open [options]","使用 Cursor 或 VSCode 打开项目",e=>{e.reset().usage(_("Usage")+": $0 open [options]").option("editor",{alias:"e",describe:"编辑器类型(cursor/vscode/auto),默认为 auto(自动检测)",default:"auto",choices:["cursor","vscode","code","auto"]}).option("name",{alias:"n",describe:"要打开的项目名称,默认为当前目录"}).alias("h","help")},e=>{w.openEditor(e.editor,e.name)}).alias("h","help").alias("v","version").strict().fail((e,s,o)=>{U(`\n运行命令时发生错误: ${e}。\n`),console.log(_("当前可用命令列表:")),console.log("");[{cmd:"init [options]",desc:"根据模板创建一个自定义组件"},{cmd:"create project [options]",desc:"创建自定义组件项目(含工程代码)"},{cmd:"create cmp [options]",desc:"创建自定义组件"},{cmd:"preview [options]",desc:"预览指定自定义组件(仅预览组件本身内容)"},{cmd:"linkDebug",desc:"开启外链调试模式(在线上页面设计器端调试)"},{cmd:"login",desc:"登录 NeoCRM 平台(OAuth2 授权)"},{cmd:"logout",desc:"登出 NeoCRM 平台"},{cmd:"pull cmp [options]",desc:"拉取线上自定义组件"},{cmd:"delete cmp [options]",desc:"删除线上自定义组件"},{cmd:"push cmp [options]",desc:"构建并发布自定义组件到 NeoCRM 平台"},{cmd:"open [options]",desc:"使用 Cursor 或 VSCode 打开项目"}].forEach(({cmd:e,desc:s})=>{console.log(` ${l.cyan(e.padEnd(25))} ${s}`)}),console.log(""),console.log(`使用 ${l.cyan("neo <command> --help")} 查看具体命令的帮助信息。`),console.log(""),process.exit(1)}).help().updateStrings({"Usage:":_("Usage:"),"Commands:":_("Commands:"),"Options:":_("Options:")}).argv,e.__exports};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./_virtual/index.js"),s=require("figlet"),o=require("yargs"),n=require("chalk"),t=require("inquirer"),a=require("ora"),i=require("./main2.js"),p=require("./package.json.js");var c;exports.__require=function(){if(c)return e.__exports;c=1;const m=s,r=o,l=n,u=t,g=a,{neoInit:d,neoInitByCopy:h,inspect:y,neoConfigInit:b,validateProjectName:C,getCmpTypeByDir:f,NeoService:v,NeoLoginService:$,hasNeoProject:x,consoleTag:T,errorLog:U,successLog:j}=i.__require(),w=i.__require(),_=p.default,M=m.textSync("neo",{font:"Lean"}),N=w.projectConfig,q=function(e){return l.green(l.bold(e))},S={"config init":"初始化配置文件",dev:"开启本地调试模式",build:"构建生产环境代码",build2lib:"构建 UMD 模块",build2esm:"构建 ESM 模块",publish2oss:"发布到 OSS",inspect:"输出配置文件",open:"打开项目"},D={...S,init:"初始化自定义组件项目",login:"登录 NeoCRM 平台",logout:"登出 NeoCRM 平台","create project":"创建自定义组件项目","create cmp":"创建自定义组件",linkDebug:"开启外链调试模式","pull cmp":"拉取线上自定义组件","delete cmp":"删除线上自定义组件",preview:"预览自定义组件","push cmp":"发布自定义组件到平台"};return r.middleware(function(e){if(e.help||e.version)return;const s=function(e){if(!e._||0===e._.length)return"";const s=e._.join(" ");if(D[s])return s;const o=e._[0];return D[o]?o:s||o}(e);if(!s)return;const o=D[s]||s;S[s]&&(console.log(l.green(M)),console.log(l.green(`当前版本:v${_.version}.\n`))),console.log(""),console.log(l.cyan(`执行命令: ${o}`)),console.log("")}).command("init [options]","根据模板创建一个自定义组件",e=>{e.reset().usage(q("Usage")+": $0 init [options]").option("type",{alias:"t",describe:"自定义组件类型(react ts 技术栈/ vue2.0 技术栈/ react 技术栈)"}).option("name",{alias:"n",describe:"自定义组件项目名称"}).alias("h","help")},e=>{if(e.type&&e.name)x()&&(U(`${T}创建自定义组件失败,当前目录(${process.cwd()})已经是一个自定义组件项目,请勿重复创建。`),process.exit(1)),"github"===e.mode?d(e.type,e.name):h(e.type,e.name);else{const s=[],o=[{name:"react&ts 自定义组件",value:"react-ts",short:"react-ts"},{name:"Neo 自定义组件(使用平台实体数据源)",value:"neo",short:"neo"},{name:"antd 自定义组件",value:"antd",short:"antd"},{name:"echarts 自定义组件",value:"echarts",short:"echarts"},{name:"vue2 自定义组件",value:"vue2",short:"vue2"}];e.type||s.push({name:"type",type:"list",message:"请选择您要创建的自定义组件类型: ",default:"react-ts",choices:o}),e.name||s.push({name:"name",type:"input",message:"请设置自定义组件项目名称(默认 neoCustomCmp):",default:"neoCustomCmp"}),u.prompt(s).then(s=>{const{isValid:o,errors:n}=C(s.name);o||(U(n.join("\n")),process.exit(1)),"github"===e.mode?d(s.type,s.name):h(s.type,s.name)})}}).command("config init","创建 neo.config.js 配置文件",e=>{e.reset().usage(q("Usage")+": $0 config init").alias("h","help")},()=>{b("neo.config.js")}).command("login","登录 NeoCRM 平台(OAuth2 授权)",e=>{e.reset().usage(q("Usage")+": $0 login").alias("h","help")},async()=>{try{const e=new $(N.neoConfig);await e.login(),process.exit(0)}catch(e){U(`\n登录失败: ${e.message||e.msg}`),process.exit(1)}}).command("logout","登出 NeoCRM 平台",e=>{e.reset().usage(q("Usage")+": $0 logout").alias("h","help")},async()=>{try{const e=new $(N.neoConfig);await e.logout(),process.exit(0)}catch(e){U(`\n登出失败: ${e.message||e.msg}`),process.exit(1)}}).command("create","创建项目或者组件",e=>e.command("project [options]","创建自定义组件项目(含工程代码)",e=>{e.reset().usage(q("Usage")+": $0 project [options]").option("name",{alias:"n",describe:"自定义组件项目名称"}).alias("h","help")},e=>{if(e.name)w.createCmpProjectByTemplate(e.name);else{const e=[{name:"name",type:"input",message:"请设置自定义组件项目名称:"}];u.prompt(e).then(e=>{const{isValid:s,errors:o}=C(e.name);s||(U(o.join("\n")),process.exit(1)),e.name?w.createCmpProjectByTemplate(e.name):(U("自定义组件项目名称不能为空。"),process.exit(1))})}}).command("cmp [options]","创建自定义组件",e=>{e.reset().usage(q("Usage")+": $0 cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.createCmpByTemplate(e.name);else{const e=[{name:"name",type:"input",message:"请设置自定义组件名称:"}];u.prompt(e).then(e=>{e.name?w.createCmpByTemplate(e.name):(U("自定义组件名称不能为空。"),process.exit(1))})}})).command("pull cmp [options]","拉取线上自定义组件",e=>{e.reset().usage(q("Usage")+": $0 pull cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},async e=>{if(e.name)w.pullCmp(e.name);else{const e=new v(N.neoConfig),s=g("正在拉取线上自定义组件列表...").start(),o=await e.getCustomCmpList();0===o.length&&(U("当前租户暂无任何自定义组件。"),process.exit(1)),s.stop("线上自定义组件列表拉取成功。");const n=[{name:"cmpType",type:"list",message:"请选择要拉取的自定义组件:",choices:o.map(e=>({name:`${e.label}(${e.cmpType})`,value:e.cmpType}))}];u.prompt(n).then(s=>{s.cmpType?w.pullCmp(s.cmpType,e):(U("自定义组件名称不能为空。"),process.exit(1))})}}).command("delete cmp [options]","删除线上自定义组件",e=>{e.reset().usage(q("Usage")+": $0 delete cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},async e=>{if(e.name)w.deleteCmp(e.name);else{const e=new v(N.neoConfig),s=g("正在获取线上自定义组件列表...").start(),o=await e.getCustomCmpList();0===o.length&&(U("当前租户暂无任何自定义组件。"),process.exit(1)),s.stop("线上自定义组件列表获取成功。");const n=[{name:"cmpType",type:"list",message:"请选择要删除的自定义组件:",choices:o.map(e=>({name:`${e.label}(${e.cmpType})`,value:e.cmpType}))}];u.prompt(n).then(s=>{s.cmpType?w.deleteCmp(s.cmpType,e):(U("自定义组件名称不能为空。"),process.exit(1))})}}).command("preview [options]","预览指定自定义组件(仅预览组件本身内容)",e=>{e.reset().usage(q("Usage")+": $0 preview [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.previewCmp(e.name);else{const e=f();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要预览的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要预览的自定义组件。"),process.exit(1)),w.previewCmp(e.cmpType)})}}).command("dev","开启本地调试模式",e=>{e.reset().usage(q("Usage")+": $0 dev").alias("h","help")},()=>{w.dev()}).command("linkDebug","开启外链调试模式(在线上页面设计器端调试)",e=>{e.reset().usage(q("Usage")+": $0 linkDebug").alias("h","help")},e=>{w.linkDebug()}).command("build","构建生产环境代码",e=>{e.reset().usage(q("Usage")+": $0 build").alias("h","help")},e=>{w.build()}).command("build2lib","构建 UMD 模块",e=>{e.reset().usage(q("Usage")+": $0 build2lib").alias("h","help")},e=>{w.build2lib()}).command("publish2oss [options]","发布到oss",e=>{e.reset().usage(q("Usage")+": $0 publish2oss [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.publish2oss(e.name);else{const e=f();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要发布的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要发布的自定义组件。"),process.exit(1)),w.publish2oss(e.cmpType)})}}).command("push cmp [options]","构建并发布自定义组件到 NeoCRM 平台",e=>{e.reset().usage(q("Usage")+": $0 push cmp [options]").option("name",{alias:"n",describe:"自定义组件名称"}).alias("h","help")},e=>{if(e.name)w.pushCmp(e.name);else{const e=f();0===e.length&&(U("当前自定义组件目录中未找到自定义组件。(./src/components 目录下)"),process.exit(1));const s=[{name:"cmpType",type:"list",message:"请选择要发布的自定义组件:",choices:e.map(e=>({name:e,value:e}))}];u.prompt(s).then(e=>{e.cmpType||(U("未选择要发布的自定义组件。"),process.exit(1)),w.pushCmp(e.cmpType)})}}).command("build2esm","构建 ESM 模块",e=>{e.reset().usage(q("Usage")+": $0 build2esm").alias("h","help")},()=>{w.build2esm()}).command("inspect","输出当前配置文件",e=>{e.reset().usage(q("Usage")+": $0 inspect").option("type",{alias:"t",describe:"环境类型(本地调试环境/生产环境/library构建环境)",default:"build"}).alias("h","help")},e=>{y(e.type)}).command("open [options]","使用 Cursor 或 VSCode 打开项目",e=>{e.reset().usage(q("Usage")+": $0 open [options]").option("editor",{alias:"e",describe:"编辑器类型(cursor/vscode/auto),默认为 auto(自动检测)",default:"auto",choices:["cursor","vscode","code","auto"]}).option("name",{alias:"n",describe:"要打开的项目名称,默认为当前目录"}).alias("h","help")},e=>{w.openEditor(e.editor,e.name)}).alias("h","help").alias("v","version").strict().fail((e,s,o)=>{U(`\n运行命令时发生错误: ${e}。\n`),console.log(q("当前可用命令列表:")),console.log("");[{cmd:"init [options]",desc:"根据模板创建一个自定义组件"},{cmd:"create project [options]",desc:"创建自定义组件项目(含工程代码)"},{cmd:"create cmp [options]",desc:"创建自定义组件"},{cmd:"preview [options]",desc:"预览指定自定义组件(仅预览组件本身内容)"},{cmd:"linkDebug",desc:"开启外链调试模式(在线上页面设计器端调试)"},{cmd:"login",desc:"登录 NeoCRM 平台(OAuth2 授权)"},{cmd:"logout",desc:"登出 NeoCRM 平台"},{cmd:"pull cmp [options]",desc:"拉取线上自定义组件"},{cmd:"delete cmp [options]",desc:"删除线上自定义组件"},{cmd:"push cmp [options]",desc:"构建并发布自定义组件到 NeoCRM 平台"},{cmd:"open [options]",desc:"使用 Cursor 或 VSCode 打开项目"}].forEach(({cmd:e,desc:s})=>{console.log(` ${l.cyan(e.padEnd(25))} ${s}`)}),console.log(""),console.log(`使用 ${l.cyan("neo <command> --help")} 查看具体命令的帮助信息。`),console.log(""),process.exit(1)}).help().updateStrings({"Usage:":q("Usage:"),"Commands:":q("Commands:"),"Options:":q("Options:")}).argv,e.__exports};
package/dist/main2.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("akfun");require("lodash");const r=require("./module/neoInit.js"),i=require("./module/neoInitByCopy.js"),s=require("./module/inspect.js"),t=require("./utils/neoConfigInit.js"),o=require("./utils/neoParams.js"),u=require("./config/index.js"),l=require("./oss/publish2oss.js"),p=require("./neo/pushCmp.js"),n=require("./neo/pullCmp.js"),c=require("./neo/deleteCmp.js"),d=require("./utils/cmpUtils/previewCmp.js"),b=require("./utils/generateEntries.js"),m=require("./utils/cmpUtils/createCmpByTemplate.js"),a=require("./utils/projectUtils/createCmpProjectByTemplate.js"),q=require("./utils/projectUtils/openProject.js"),_=require("./utils/configureNeoBuild.js"),y=require("./utils/common.js"),g=require("./utils/projectNameValidator.js"),j=require("./utils/cmpUtils/getCmpTypeByDir.js"),v=require("./neo/neoService.js"),T=require("./neo/neoLogin.js"),f=require("./utils/projectUtils/hasNeoProject.js");var C,x;exports.__require=function(){if(x)return C;x=1;const h=e,E=r.__require(),N=i.__require(),w=s.__require(),B=t.__require(),{consoleTag:D}=o.__require(),P=u.__require(),k=l.__require(),I=p.__require(),L=n.__require(),M=c.__require(),O=d.__require(),U=b.__require(),S=m.__require(),R=a.__require(),A=q.__require(),{configureNeoBuild:V}=_.__require(),{errorLog:z,successLog:F}=y.__require(),{validateProjectName:G}=g.__require(),H=j.__require(),J=v.__require(),K=T.__require(),Q=f.__require();function W(e,r){const{entryType:i,cmpType:s}=r;let t=[],o={};try{const{entries:r,cmpTypes:u,defaultExports:l}=U({configEntry:e.entry,disableAutoRegister:e.disableAutoRegister,componentsDir:P.componentsDir,entryType:i,cmpType:s});r&&Object.keys(r).length>0&&(e.entry=r,t=u,console.info("已自动生成 entry 入口配置:",r)),o=l}catch(e){z(e.message),process.exit(1)}return{cmpTypes:t,defaultExports:o}}function X(e){return Object.assign(P.build2lib,e)}return C={neoInit:E,neoInitByCopy:N,inspect:w,neoConfigInit:B,projectConfig:P,consoleTag:D,errorLog:z,successLog:F,validateProjectName:G,getCmpTypeByDir:H,NeoService:J,NeoLoginService:K,hasNeoProject:Q,createCmpProjectByTemplate:R,createCmpByTemplate:S,dev:()=>{P.dev||(z("未找到 dev 相关配置。"),process.exit(1)),h.dev(P,D)},previewCmp:e=>{e||(z("请输入要预览的组件名称。"),process.exit(1)),P.preview||(z("未找到 preview 相关配置。"),process.exit(1)),P.dev=Object.assign(P.dev,P.preview),delete P.preview,O(P,e)},linkDebug:()=>{P.linkDebug||(z("未找到 debug 相关配置。"),process.exit(1)),P.dev=Object.assign(P.dev,P.linkDebug),delete P.linkDebug,delete P.dev.ignoreNodeModules,P.webpack.ignoreNodeModules=!1;const{cmpTypes:e,defaultExports:r}=W(P.dev,{entryType:"linkDebug"});V(P.dev,{cmpTypes:e,defaultExports:r,verbose:!0,excludeModel:!1}),h.dev(P,D)},build:()=>h.build("build",P,D),build2lib:()=>{W(P.build2lib,{entryType:"widget"}),h.build("lib",P,D)},publish2oss:e=>{const r=P.publish2oss;P.build2lib=X(r);const{cmpTypes:i,defaultExports:s}=W(P.build2lib,{entryType:"widget",cmpType:e});V(P.build2lib,{cmpTypes:i,defaultExports:s,verbose:!0,excludeModel:!0}),h.build("lib",P,D,()=>{k(r.ossType,r.ossConfig,r.assetsRoot)})},pushCmp:e=>{const{neoConfig:r,pushCmp:i}=P,s=Object.assign({},i,r);P.build2lib=X(s);const{cmpTypes:t,defaultExports:o}=W(P.build2lib,{entryType:"widget",cmpType:e});V(P.build2lib,{cmpTypes:t,defaultExports:o,verbose:!1,excludeModel:!0}),h.build("lib",P,D,()=>{I(s,e)})},pullCmp:(e,r)=>{L(e,P.neoConfig,r)},deleteCmp:(e,r)=>{M(e,P.neoConfig,r)},build2esm:()=>h.build2esm(P,D),openEditor:A},C};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("akfun");require("lodash");const r=require("./module/neoInit.js"),i=require("./module/neoInitByCopy.js"),s=require("./module/inspect.js"),t=require("./utils/neoConfigInit.js"),o=require("./utils/neoParams.js"),u=require("./config/index.js"),l=require("./oss/publish2oss.js"),p=require("./neo/pushCmp.js"),n=require("./neo/pullCmp.js"),c=require("./neo/deleteCmp.js"),d=require("./utils/cmpUtils/previewCmp.js"),b=require("./utils/generateEntries.js"),m=require("./utils/cmpUtils/createCmpByTemplate.js"),a=require("./utils/projectUtils/createCmpProjectByTemplate.js"),q=require("./utils/projectUtils/openProject.js"),_=require("./utils/configureNeoBuild.js"),y=require("./utils/common.js"),g=require("./utils/projectNameValidator.js"),j=require("./utils/cmpUtils/getCmpTypeByDir.js"),v=require("./neo/neoService.js"),T=require("./neo/neoLogin.js"),f=require("./utils/projectUtils/hasNeoProject.js");var C,x;exports.__require=function(){if(x)return C;x=1;const h=e,E=r.__require(),N=i.__require(),w=s.__require(),B=t.__require(),{consoleTag:D}=o.__require(),P=u.__require(),k=l.__require(),I=p.__require(),L=n.__require(),M=c.__require(),O=d.__require(),U=b.__require(),S=m.__require(),R=a.__require(),A=q.__require(),{configureNeoBuild:V}=_.__require(),{errorLog:z,successLog:F}=y.__require(),{validateProjectName:G}=g.__require(),H=j.__require(),J=v.__require(),K=T.__require(),Q=f.__require();function W(e,r){const{entryType:i,cmpType:s}=r;let t=[],o={};try{const{entries:r,cmpTypes:u,defaultExports:l}=U({configEntry:e.entry,disableAutoRegister:e.disableAutoRegister,componentsDir:P.componentsDir,entryType:i,cmpType:s});r&&Object.keys(r).length>0&&(e.entry=r,t=u,console.info("已自动生成 entry 入口配置:",r)),o=l}catch(e){z(e.message||e.msg),process.exit(1)}return{cmpTypes:t,defaultExports:o}}function X(e){return Object.assign(P.build2lib,e)}return C={neoInit:E,neoInitByCopy:N,inspect:w,neoConfigInit:B,projectConfig:P,consoleTag:D,errorLog:z,successLog:F,validateProjectName:G,getCmpTypeByDir:H,NeoService:J,NeoLoginService:K,hasNeoProject:Q,createCmpProjectByTemplate:R,createCmpByTemplate:S,dev:()=>{P.dev||(z("未找到 dev 相关配置。"),process.exit(1)),h.dev(P,D)},previewCmp:e=>{e||(z("请输入要预览的组件名称。"),process.exit(1)),P.preview||(z("未找到 preview 相关配置。"),process.exit(1)),P.dev=Object.assign(P.dev,P.preview),delete P.preview,O(P,e)},linkDebug:()=>{P.linkDebug||(z("未找到 debug 相关配置。"),process.exit(1)),P.dev=Object.assign(P.dev,P.linkDebug),delete P.linkDebug,delete P.dev.ignoreNodeModules,P.webpack.ignoreNodeModules=!1;const{cmpTypes:e,defaultExports:r}=W(P.dev,{entryType:"linkDebug"});V(P.dev,{cmpTypes:e,defaultExports:r,verbose:!0,excludeModel:!1}),h.dev(P,D)},build:()=>h.build("build",P,D),build2lib:()=>{W(P.build2lib,{entryType:"widget"}),h.build("lib",P,D)},publish2oss:e=>{const r=P.publish2oss;P.build2lib=X(r);const{cmpTypes:i,defaultExports:s}=W(P.build2lib,{entryType:"widget",cmpType:e});V(P.build2lib,{cmpTypes:i,defaultExports:s,verbose:!0,excludeModel:!0}),h.build("lib",P,D,()=>{k(r.ossType,r.ossConfig,r.assetsRoot)})},pushCmp:e=>{const{neoConfig:r,pushCmp:i}=P,s=Object.assign({},i,r);P.build2lib=X(s);const{cmpTypes:t,defaultExports:o}=W(P.build2lib,{entryType:"widget",cmpType:e});V(P.build2lib,{cmpTypes:t,defaultExports:o,verbose:!1,excludeModel:!0}),h.build("lib",P,D,()=>{I(s,e)})},pullCmp:(e,r)=>{L(e,P.neoConfig,r)},deleteCmp:(e,r)=>{M(e,P.neoConfig,r)},build2esm:()=>h.build2esm(P,D),openEditor:A},C};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("ora"),r=require("./neoService.js"),t=require("../utils/common.js");var o,s;exports.__require=function(){if(s)return o;s=1;const i=e,n=r.__require(),{errorLog:c,successLog:u}=t.__require();return o=async(e,r,t)=>{if(!r)return void c("未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。");const o=i("正在删除组件...").start();try{let s=t,i=[],a=null;t?i=t.cmpList||[]:(s=new n(r),o.info("正在获取自定义组件列表..."),i=await s.getCustomCmpList()),0===i.length&&(c("删除失败,当前租户暂无任何自定义组件。",o),process.exit(1)),a=s.getCmpInfoByCmpType(e),a||(c(`删除失败,当前租户不存在${e}自定义组件。`,o),process.exit(1)),o.info(`正在删除${e}自定义组件...`),await s.deleteCmp(e),u(`已成功删除${e}自定义组件!\n`,o)}catch(e){c(`删除自定义组件失败: ${e.message}`,o),process.exit(1)}},o};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("ora"),r=require("./neoService.js"),t=require("../utils/common.js");var o,s;exports.__require=function(){if(s)return o;s=1;const i=e,n=r.__require(),{errorLog:c,successLog:u}=t.__require();return o=async(e,r,t)=>{if(!r)return void c("未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。");const o=i("正在删除组件...").start();try{let s=t,i=[],a=null;t?i=t.cmpList||[]:(s=new n(r),o.info("正在获取自定义组件列表..."),i=await s.getCustomCmpList()),0===i.length&&(c("删除失败,当前租户暂无任何自定义组件。",o),process.exit(1)),a=s.getCmpInfoByCmpType(e),a||(c(`删除失败,当前租户不存在${e}自定义组件。`,o),process.exit(1)),o.info(`正在删除${e}自定义组件...`),await s.deleteCmp(e),u(`已成功删除${e}自定义组件!\n`,o)}catch(e){c(`删除自定义组件失败: ${e.message||e.msg}`,o),process.exit(1)}},o};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("node:fs"),n=require("node:path"),s=require("ora"),r=require("node:http"),o=require("node:url"),i=require("open"),c=require("node:net");require("portfinder");const a=require("../utils/common.js"),l=require("../config/auth.config.js");var h,p;exports.__require=function(){if(p)return h;p=1;const u=e,d=t,g=n,k=s,y=r,_=o,m=i,T=c,{errorLog:f,successLog:w}=a.__require(),S=l.__require();return h=class{constructor(e={}){const{loginURL:t,tokenAPI:n}=e;if(!t||!n)throw new Error("auth.config.js 配置不完整,需要包含 loginURL、tokenAPI");this.loginURL=t,this.tokenAPI=n,this.response_type=S.response_type||"code",this.client_id=S.client_id,this.client_secret=S.client_secret,this.scope=S.scope||"all",this.oauthType=S.oauthType||"standard",this.access_type=S.access_type||"offline",this.grant_type=S.grant_type||"authorization_code",this.tokenDir=g.join(process.cwd(),".neo-cli"),this.tokenFile=g.join(this.tokenDir,"token.json"),this.pageDir=g.join(__dirname,"../../template/pageHtml"),this.authErrorTemplate=g.join(this.pageDir,"auth-error.html"),this.authSuccessTemplate=g.join(this.pageDir,"auth-success.html"),this.tokenErrorTemplate=g.join(this.pageDir,"token-error.html"),this.authFailedTemplate=g.join(this.pageDir,"auth-failed.html")}ensureTokenDir(){d.existsSync(this.tokenDir)||d.mkdirSync(this.tokenDir,{recursive:!0})}saveToken(e){this.ensureTokenDir();const t={...e,savedAt:Date.now(),expiresAt:Date.now()+1e3*(e.expires_in||7200)};d.writeFileSync(this.tokenFile,JSON.stringify(t,null,2),"utf-8")}readToken(){if(!d.existsSync(this.tokenFile))return null;try{return JSON.parse(d.readFileSync(this.tokenFile,"utf-8"))}catch(e){return f(`读取 token 文件失败: ${e.message}`),null}}isTokenExpired(e){return!e||!e.expiresAt||Date.now()>=e.expiresAt-3e5}clearToken(){d.existsSync(this.tokenFile)&&d.unlinkSync(this.tokenFile)}getRedirectURI(e){return`http://localhost:${e}`}buildAuthUrl(e){const t=new URLSearchParams({response_type:this.response_type,client_id:this.client_id,redirect_uri:e,scope:this.scope,oauthType:this.oauthType,access_type:this.access_type});return`${this.loginURL}?${t.toString()}`}async openBrowser(e){try{await m(e)}catch(t){f(`无法自动打开浏览器: ${t.message}`),console.log(`\n请手动访问以下 URL 进行授权:\n${e}\n`)}}getHtmlTemplate(e,t={}){try{let n=d.readFileSync(e,"utf-8");return Object.keys(t).forEach(e=>{const s=`{{${e}}}`;n=n.replace(new RegExp(s,"g"),t[e])}),n}catch(e){return f(`读取 HTML 模板失败: ${e.message}`),"<html><body><h1>页面加载失败</h1></body></html>"}}async isPortInUse(e){return new Promise(t=>{const n=T.createServer();n.once("error",e=>{"EADDRINUSE"===e.code?t(!0):t(!1)}),n.once("listening",()=>{n.once("close",()=>{t(!1)}),n.close()}),n.listen(e)})}async startCallbackServer(){let e=S.redirectUri,t=new URL(e),n=parseInt(t.port,10);await this.isPortInUse(n)&&(f(`\n警告: 端口 ${n} 已被占用,请调整 redirectUri 配置项,使其指向一个未被占用的端口。`),process.exit(1));const s=new Promise((s,r)=>{const o=y.createServer(async(n,i)=>{const c=_.parse(n.url,!0);if(c.pathname===t.pathname||"/"===c.pathname){const t=c.query.code,n=c.query.error;if(n){i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"});const e=this.getHtmlTemplate(this.authErrorTemplate,{ERROR:n});return i.end(e),o.close(),void r(new Error(`授权失败: ${n}`))}if(t)try{const n=await this.getTokenByCode(t,e);this.saveToken(n);const r=n.tenant_id||"未返回",c=n.instance_uri||"未返回";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"});const a=this.getHtmlTemplate(this.authSuccessTemplate,{TENANT_ID:r,INSTANCE_URI:c});return i.end(a),o.close(),void s({code:t,tokenData:n})}catch(e){i.writeHead(500,{"Content-Type":"text/html; charset=utf-8"});const t=this.getHtmlTemplate(this.tokenErrorTemplate,{ERROR:e});return i.end(t),o.close(),void r(e)}i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"});const a=this.getHtmlTemplate(this.authFailedTemplate);i.end(a),o.close(),r(new Error("未获取到授权码"))}else i.writeHead(404,{"Content-Type":"text/plain"}),i.end("Not Found")});o.on("error",e=>{"EADDRINUSE"===e.code?r(new Error(`端口 ${n} 已被占用,无法启动回调服务器`)):r(e)}),o.listen(n,()=>{console.log(`\n本地回调服务器已启动,监听端口: ${n}`),console.log(`回调地址: ${e}`)}),setTimeout(()=>{o.close(),r(new Error("授权超时,请重试"))},3e5)});return{redirectUri:e,getCodeAndTokenPromise:s}}async getTokenByCode(e,t){const n=k("正在获取 access token...").start();try{const s=new URLSearchParams;s.append("grant_type",this.grant_type),s.append("client_id",this.client_id),s.append("client_secret",this.client_secret),s.append("code",e),s.append("redirect_uri",t);const r=(await u.post(this.tokenAPI,s.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return r&&r.access_token||(f("获取 token 失败:响应中未包含 access_token",n),f(`响应数据: ${JSON.stringify(r)}`),process.exit(1)),w("成功获取 access token",n),r}catch(e){f("获取 token 失败",n),f(`\n获取 token 失败: ${e.message}`),e.response&&f(`响应数据: ${JSON.stringify(e.response.data)}`),process.exit(1)}}async refreshToken(e){const t=k("正在刷新授权信息(token)...").start();try{const n=new URLSearchParams;n.append("grant_type","refresh_token"),n.append("client_id",this.client_id),n.append("client_secret",this.client_secret),n.append("refresh_token",e);const s=(await u.post(this.tokenAPI,n.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return s&&s.access_token?(w("刷新授权信息成功(token)。",t),s):(f("刷新授权信息失败:响应中未包含 access_token",t),f(`响应数据: ${JSON.stringify(s)}`),null)}catch(e){return f("刷新授权信息失败",t),f(`\n刷新授权信息失败: ${e.message}`),e.response&&f(`响应数据: ${JSON.stringify(e.response.data)}`),null}}async login(){console.log("\n========== NeoCRM 登录授权 ==========\n");try{const{redirectUri:e,getCodeAndTokenPromise:t}=await this.startCallbackServer(),n=this.buildAuthUrl(e);console.log("授权 URL:",n),console.log("\n正在打开浏览器进行授权..."),await this.openBrowser(n);const{code:s,tokenData:r}=await t;return w("\n✓ 已获取授权码"),console.log("\n========== 登录成功 ==========\n"),console.log(`已缓存授权信息到: ${this.tokenFile}`),console.log(`实例地址: ${r.instance_uri||"未返回"}`),console.log(`租户 ID: ${r.tenant_id||"未返回"}`),console.log(`授权信息有效期(access_token): ${r.expires_in||7200} 秒`),console.log(`自动刷新授权信息有效期(refresh_token): ${r.refresh_token_expires_in||2592e3} 秒`),r}catch(e){f(`\n登录失败: ${e.message}`),process.exit(1)}}async logout(){if(console.log("\n========== NeoCRM 登出 ==========\n"),d.existsSync(this.tokenFile))try{this.clearToken(),w("已清除授权信息,下次登录需要重新授权。"),console.log("\n登出成功!\n")}catch(e){f(`登出失败: ${e.message}`),process.exit(1)}else console.log("当前未登录,无需登出。")}async getValidToken(){const e=this.readToken();if(e||(f("未找到授权信息,请先执行 neo login 进行登录。"),process.exit(1)),this.isTokenExpired(e)){console.log("授权信息已过期,正在尝试刷新..."),e.refresh_token||(f("自动刷新授权信息失败,请重新登录(neo login)。"),process.exit(1));const t=await this.refreshToken(e.refresh_token);return t||(f("刷新授权信息失败,请重新登录 (neo login)"),process.exit(1)),this.saveToken(t),t}return e}async getAccessToken(){return await this.getValidToken()}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("node:fs"),n=require("node:path"),s=require("ora"),r=require("node:http"),o=require("node:url"),i=require("open"),c=require("node:net");require("portfinder");const a=require("../utils/common.js"),l=require("../config/auth.config.js");var h,p;exports.__require=function(){if(p)return h;p=1;const u=e,d=t,g=n,y=s,k=r,m=o,_=i,T=c,{errorLog:w,successLog:f}=a.__require(),S=l.__require();return h=class{constructor(e={}){const{loginURL:t,tokenAPI:n}=e;if(!t||!n)throw new Error("auth.config.js 配置不完整,需要包含 loginURL、tokenAPI");this.loginURL=t,this.tokenAPI=n,this.response_type=S.response_type||"code",this.client_id=S.client_id,this.client_secret=S.client_secret,this.scope=S.scope||"all",this.oauthType=S.oauthType||"standard",this.access_type=S.access_type||"offline",this.grant_type=S.grant_type||"authorization_code",this.tokenDir=g.join(process.cwd(),".neo-cli"),this.tokenFile=g.join(this.tokenDir,"token.json"),this.pageDir=g.join(__dirname,"../../template/pageHtml"),this.authErrorTemplate=g.join(this.pageDir,"auth-error.html"),this.authSuccessTemplate=g.join(this.pageDir,"auth-success.html"),this.tokenErrorTemplate=g.join(this.pageDir,"token-error.html"),this.authFailedTemplate=g.join(this.pageDir,"auth-failed.html")}ensureTokenDir(){d.existsSync(this.tokenDir)||d.mkdirSync(this.tokenDir,{recursive:!0})}saveToken(e){this.ensureTokenDir();const t={...e,savedAt:Date.now(),expiresAt:Date.now()+1e3*(e.expires_in||7200)};d.writeFileSync(this.tokenFile,JSON.stringify(t,null,2),"utf-8")}readToken(){if(!d.existsSync(this.tokenFile))return null;try{return JSON.parse(d.readFileSync(this.tokenFile,"utf-8"))}catch(e){return w(`读取 token 文件失败: ${e.message||e.msg}`),null}}isTokenExpired(e){return!e||!e.expiresAt||Date.now()>=e.expiresAt-3e5}clearToken(){d.existsSync(this.tokenFile)&&d.unlinkSync(this.tokenFile)}getRedirectURI(e){return`http://localhost:${e}`}buildAuthUrl(e){const t=new URLSearchParams({response_type:this.response_type,client_id:this.client_id,redirect_uri:e,scope:this.scope,oauthType:this.oauthType,access_type:this.access_type});return`${this.loginURL}?${t.toString()}`}async openBrowser(e){try{await _(e)}catch(t){w(`无法自动打开浏览器: ${t.message||t.msg}`),console.log(`\n请手动访问以下 URL 进行授权:\n${e}\n`)}}getHtmlTemplate(e,t={}){try{let n=d.readFileSync(e,"utf-8");return Object.keys(t).forEach(e=>{const s=`{{${e}}}`;n=n.replace(new RegExp(s,"g"),t[e])}),n}catch(e){return w(`读取 HTML 模板失败: ${e.message||e.msg}`),"<html><body><h1>页面加载失败</h1></body></html>"}}async isPortInUse(e){return new Promise(t=>{const n=T.createServer();n.once("error",e=>{"EADDRINUSE"===e.code?t(!0):t(!1)}),n.once("listening",()=>{n.once("close",()=>{t(!1)}),n.close()}),n.listen(e)})}async startCallbackServer(){let e=S.redirectUri,t=new URL(e),n=parseInt(t.port,10);await this.isPortInUse(n)&&(w(`\n警告: 端口 ${n} 已被占用,请调整 redirectUri 配置项,使其指向一个未被占用的端口。`),process.exit(1));const s=new Promise((s,r)=>{const o=k.createServer(async(n,i)=>{const c=m.parse(n.url,!0);if(c.pathname===t.pathname||"/"===c.pathname){const t=c.query.code,n=c.query.error;if(n){i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"});const e=this.getHtmlTemplate(this.authErrorTemplate,{ERROR:n});return i.end(e),o.close(),void r(new Error(`授权失败: ${n}`))}if(t)try{const n=await this.getTokenByCode(t,e);this.saveToken(n);const r=n.tenant_id||"未返回",c=n.instance_uri||"未返回";i.writeHead(200,{"Content-Type":"text/html; charset=utf-8"});const a=this.getHtmlTemplate(this.authSuccessTemplate,{TENANT_ID:r,INSTANCE_URI:c});return i.end(a),o.close(),void s({code:t,tokenData:n})}catch(e){i.writeHead(500,{"Content-Type":"text/html; charset=utf-8"});const t=this.getHtmlTemplate(this.tokenErrorTemplate,{ERROR:e});return i.end(t),o.close(),void r(e)}i.writeHead(400,{"Content-Type":"text/html; charset=utf-8"});const a=this.getHtmlTemplate(this.authFailedTemplate);i.end(a),o.close(),r(new Error("未获取到授权码"))}else i.writeHead(404,{"Content-Type":"text/plain"}),i.end("Not Found")});o.on("error",e=>{"EADDRINUSE"===e.code?r(new Error(`端口 ${n} 已被占用,无法启动回调服务器`)):r(e)}),o.listen(n,()=>{console.log(`\n本地回调服务器已启动,监听端口: ${n}`),console.log(`回调地址: ${e}`)}),setTimeout(()=>{o.close(),r(new Error("授权超时,请重试"))},3e5)});return{redirectUri:e,getCodeAndTokenPromise:s}}async getTokenByCode(e,t){const n=y("正在获取 access token...").start();try{const s=new URLSearchParams;s.append("grant_type",this.grant_type),s.append("client_id",this.client_id),s.append("client_secret",this.client_secret),s.append("code",e),s.append("redirect_uri",t);const r=(await u.post(this.tokenAPI,s.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return r&&r.access_token||(w("获取 token 失败:响应中未包含 access_token",n),w(`响应数据: ${JSON.stringify(r)}`),process.exit(1)),f("成功获取 access token",n),r}catch(e){w("获取 token 失败",n),w(`\n获取 token 失败: ${e.message||e.msg}`),e.response&&w(`响应数据: ${JSON.stringify(e.response.data)}`),process.exit(1)}}async refreshToken(e){const t=y("正在刷新授权信息(token)...").start();try{const n=new URLSearchParams;n.append("grant_type","refresh_token"),n.append("client_id",this.client_id),n.append("client_secret",this.client_secret),n.append("refresh_token",e);const s=(await u.post(this.tokenAPI,n.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}})).data;return s&&s.access_token?(f("刷新授权信息成功(token)。",t),s):(w("刷新授权信息失败:响应中未包含 access_token",t),w(`响应数据: ${JSON.stringify(s)}`),null)}catch(e){return w("刷新授权信息失败",t),w(`\n刷新授权信息失败: ${e.message||e.msg}`),e.response&&w(`响应数据: ${JSON.stringify(e.response.data)}`),null}}async login(){console.log("\n========== NeoCRM 登录授权 ==========\n");try{const{redirectUri:e,getCodeAndTokenPromise:t}=await this.startCallbackServer(),n=this.buildAuthUrl(e);console.log("授权 URL:",n),console.log("\n正在打开浏览器进行授权..."),await this.openBrowser(n);const{code:s,tokenData:r}=await t;return f("\n✓ 已获取授权码"),console.log("\n========== 登录成功 ==========\n"),console.log(`实例地址: ${r.instance_uri||"未返回"}`),console.log(`租户 ID: ${r.tenant_id||"未返回"}`),r}catch(e){w(`\n登录失败: ${e.message||e.msg}`),process.exit(1)}}async logout(){if(console.log("\n========== NeoCRM 登出 ==========\n"),d.existsSync(this.tokenFile))try{this.clearToken(),f("已清除授权信息,下次登录需要重新授权。"),console.log("\n登出成功!\n")}catch(e){w(`登出失败: ${e.message||e.msg}`),process.exit(1)}else console.log("当前未登录,无需登出。")}async getValidToken(){const e=this.readToken();if(e||(w("未找到授权信息,请先执行 neo login 进行登录。"),process.exit(1)),this.isTokenExpired(e)){console.log("授权信息已过期,正在尝试刷新..."),e.refresh_token||(w("自动刷新授权信息失败,请重新登录(neo login)。"),process.exit(1));const t=await this.refreshToken(e.refresh_token);return t||(w("刷新授权信息失败,请重新登录 (neo login)"),process.exit(1)),this.saveToken(t),t}return e}async getAccessToken(){return await this.getValidToken()}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("form-data"),s=require("node:fs"),o=require("node:path"),i=require("ora"),n=require("lodash"),r=require("akfun"),a=require("./neoLogin.js"),c=require("../utils/projectUtils/updatePublishLog.js"),u=require("../utils/common.js");var h,p;exports.__require=function(){if(p)return h;p=1;const l=e,d=t,m=s,f=o,y=i,w=n,{resolve:g}=r,k=a.__require(),$=c.__require(),{getFramework:x,errorLog:A,successLog:C}=u.__require(),T="https://crm.xiaoshouyi.com",F="https://login-cd.xiaoshouyi.com/auc/oauth2/auth",L="https://login.xiaoshouyi.com/auc/oauth2/token",b="/rest/metadata/v3.0/ui/customComponents",S="/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent",P="/rest/metadata/v3.0/ui/components/filter?custom=true",U=e=>`/rest/metadata/v3.0/ui/customComponents/${e}/codeLib`,B="/rest/metadata/v3.0/ui/customComponents/actions/upload",E=["cmpType","label","componentCategory","description","framework","icon","iconUrl","orderNo","version","propsSchema","defaultProps","previewProps","events","functions","asset","modelAsset","cssAsset","codeLib"];return h=class{constructor(e={}){const{assetsRoot:t,neoBaseURL:s,tokenAPI:o,loginURL:i,auth:n,authType:r}=e||{};this.authType=r||"oauth2","password"!==this.authType||n||(A("密码授权模式时,neo.config.js / neoConfig / auth 配置不能为空"),process.exit(1)),"password"===this.authType?n.client_id&&n.client_secret&&n.username&&n.password||(A("neo.config.js / neoConfig / auth 配置不完整(password 模式),需要包含 client_id、client_secret、username、password"),process.exit(1)):"oauth2"===this.authType?i&&o||(A("neo.config.js / neoConfig 配置不完整(oauth2 模式),需要包含 loginURL、tokenAPI 配置。"),process.exit(1)):(A(`不支持的授权类型: ${this.authType},可选值:oauth2、password`),process.exit(1)),this.assetsRoot=t||g("dist"),this.neoBaseURL=s||T,this.tokenAPI=o||L,this.loginURL=i||F,this.auth=n,this.cmpList=[],this.cmpInfoMap={},this.tokenCache={token:null,expiresAt:null}}buildFullUrl(e){return e.startsWith("http://")||e.startsWith("https://")?e:`${this.neoBaseURL}${e}`}uploadAPI(){return this.buildFullUrl(B)}saveAPI(){return this.buildFullUrl(S)}isTokenExpired(){return!this.tokenCache.token||!this.tokenCache.expiresAt||Date.now()>=this.tokenCache.expiresAt}async getToken(){return this.isTokenExpired()?"oauth2"===this.authType?await this.getTokenByOAuth2():await this.getTokenByPassword():this.tokenCache.token}async getTokenByPassword(){const e=y("获取 token(密码模式)...").start();if(!this.isTokenExpired())return C("使用缓存的 token。",e),this.tokenCache.token;const t=new URLSearchParams;t.append("grant_type","password"),t.append("client_id",this.auth.client_id),t.append("client_secret",this.auth.client_secret),t.append("username",this.auth.username),t.append("password",this.auth.password);const s=this.buildFullUrl(this.tokenAPI);try{const o=await l.post(s,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),i=o.data||{},{access_token:n,expires_in:r}=i;n||(A("获取 token 失败(授权配置错误):响应中未包含 access_token,"+JSON.stringify(o.data),e),process.exit(1));const a=parseInt(r)||3600;return this.tokenCache={...i,token:n,expiresAt:Date.now()+1e3*(a-60)},e.clear(),e.stop(),n}catch(o){A("获取 token 失败",e),A(`\n获取 token 失败: ${o.message}`),A(`\ntoken 授权地址: ${s}`),A(`\ntoken 请求参数: ${t}`),o.response&&A(`响应数据: ${JSON.stringify(o.response.data)}`),process.exit(1)}}async getTokenByOAuth2(){const e=y("获取 token(OAuth2 模式)...").start();try{const t={loginURL:this.loginURL,tokenAPI:this.tokenAPI},s=new k(t),o=await s.getAccessToken(),i=o.access_token;return this.tokenCache={...o,token:i,expiresAt:Date.now()+72e5},e.clear(),e.stop(),i}catch(t){A("获取 token 失败(OAuth2 模式)",e),A(`\n获取 token 失败: ${t.message}`),t.response&&A(`响应数据: ${JSON.stringify(t.response.data)}`),process.exit(1)}}async refreshToken(){return this.tokenCache={token:null,expiresAt:null},await this.getToken()}async ensureValidToken(){if(!this.tokenCache.token)return await this.getToken();if(this.isTokenExpired()){const e=y("token 已过期,正在刷新...").start();try{const t=await this.refreshToken();return C("token 刷新成功。",e),t}catch(t){throw A("token 刷新失败。",e),t}}return this.tokenCache.token}async uploadFile(e,t={}){const s=await this.ensureValidToken();if(!e||"string"!=typeof e)throw new Error(`文件路径无效: ${e}`);if(!m.existsSync(e))throw new Error(`文件不存在: ${e}`);const o=m.statSync(e);if(!o.isFile())throw new Error(`路径不是文件: ${e}`);const i=t.maxSize||5242880;if(o.size>i){const e=(o.size/1024/1024).toFixed(2),t=(i/1024/1024).toFixed(2);throw new Error(`文件大小超过限制: ${e}MB > ${t}MB`)}if(0===o.size)throw new Error(`文件为空: ${e}`);const n=f.basename(e),r=(o.size/1024).toFixed(2),a=y(`正在上传文件: ${n} (${r}KB)...`).start();try{const o=new d,i=t.fieldName||"customComponentCode",r=m.createReadStream(e);o.append(i,r,n);const c=this.uploadAPI(),u=t.timeout||6e4,h={headers:{Authorization:`Bearer ${s}`,"xsy-inner-source":"bff",...o.getHeaders()},timeout:u,maxContentLength:1/0,maxBodyLength:1/0},p=await l.post(c,o,h);let f;const y=p.data;if(200!==p.status&&201!==p.status)throw new Error(`上传失败: HTTP ${p.status}`);if("string"==typeof y)f=y.trim();else{if(!y||"object"!=typeof y)throw new Error("响应数据格式不正确: "+typeof y);if(void 0!==y.code&&200!==y.code&&0!==y.code){const e=y.message||y.msg||"未知错误";throw new Error(`上传失败: ${e} (code: ${y.code})`)}f=void 0!==y.data?y.data:void 0!==y.url?y.url:void 0!==y.fileUrl?y.fileUrl:y}if(!f)throw new Error("返回的文件地址为空");let w;return"string"==typeof f?w=f:f&&"object"==typeof f&&f.url&&(w=f.url),C(`文件上传成功: ${n} -> ${w}`,a),w}catch(t){if(A(`上传文件失败: ${t.message}, 文件路径: ${e}`,a),t.response){const e=t.response.status,s=t.response.statusText,o=t.response.data,i=t.config?.url||this.uploadAPI();if(A("\n========== 上传请求详情 =========="),A(`请求 URL: ${i}`),A(`HTTP 状态码: ${e} ${s}`),A(`响应数据: ${JSON.stringify(o)}`),A("==================================\n"),404===e)throw new Error(`上传 API 不存在 (404): ${i}\n请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n当前配置的 API 路径: ${B}`)}else t.request&&A("请求已发送但未收到响应,请检查网络连接或代理配置。");throw t}}async publish2oss(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e},o=m.readdirSync(this.assetsRoot).map(async o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;try{const e=await this.uploadFile(i);o.indexOf("Model")>-1?s.modelAsset=e:o.endsWith(".css")?s.cssAsset=e:o.endsWith(".zip")?s.codeLib=e:s.asset=e}catch(e){A(`文件上传失败(${o}):\n`),process.exit(1)}}});return await Promise.all(o),s&&s.cmpType&&(console.info("上传至 OSS 的文件信息:\n",s),$(s)),s}async getCmpAssets(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e};return m.readdirSync(this.assetsRoot).forEach(o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;const r=5242880;if(n.size>r){const e=(n.size/1024/1024).toFixed(2),t=(r/1024/1024).toFixed(2);throw new Error(`${o} 文件大小超过限制: ${e}MB > ${t}MB`)}const a={fileContent:m.createReadStream(i),fileName:o,fileSize:n.size};o.indexOf("Model")>-1?s.modelAssetFile=a:o.endsWith(".css")?s.cssAssetFile=a:o.endsWith(".zip")?s.codeLibFile=a:s.assetFile=a}}),s}async updateCustomComponent(e){const t=await this.ensureValidToken();if(!e)throw new Error("componentData 不能为空");const s=y("正在保存自定义组件信息...").start();try{const o=this.saveAPI(),i=new d;e.assetFile&&i.append("assetFile",e.assetFile.fileContent,e.assetFile.fileName),e.modelAssetFile&&i.append("modelAssetFile",e.modelAssetFile.fileContent,e.modelAssetFile.fileName),e.cssAssetFile&&i.append("cssAssetFile",e.cssAssetFile.fileContent,e.cssAssetFile.fileName),e.codeLibFile&&i.append("codeLibFile",e.codeLibFile.fileContent,e.codeLibFile.fileName),i.append("component",JSON.stringify(w.omit(e,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])));const n=await l.post(o,i,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff",...i.getHeaders()},timeout:12e4,maxContentLength:1/0,maxBodyLength:1/0}),{code:r,message:a}=n.data||{};r&&200!==r&&(A(`保存自定义组件信息失败: ${n.data.message||"未知错误"}`),process.exit(1)),s.clear(),s.stop()}catch(e){e.message?A(`保存自定义组件信息失败: ${e.message}`,s):A(`保存自定义组件信息失败: ${JSON.stringify(e)}`,s),process.exit(1)}}async getCustomCmpList(){const e=await this.ensureValidToken();try{let t=this.buildFullUrl(P);t+=`&fields=${E.join(",")}`;const s=await l.get(t,{headers:{Authorization:`Bearer ${e}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:o,message:i}=s.data||{};o&&200!==o&&(A(`获取自定义组件列表失败: ${i||"未知错误"}`),process.exit(1)),this.updateCustomCmpList(s.data.data||[])}catch(e){e.message?A(`获取自定义组件列表失败: ${e.message}`):A(`响应数据: ${JSON.stringify(e)}`),process.exit(1)}return this.cmpList||[]}getCodeLibByCmpType(e){return e?this.buildFullUrl(U(e)):null}async deleteCmp(e){const t=await this.ensureValidToken();e||(A("自定义组件名称不能为空。"),process.exit(1));let s=this.buildFullUrl(b);s+=`/${e}`;const o=await l.delete(s,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:i,message:n}=o.data||{};return i&&200!==i&&(A(`删除自定义组件失败: ${n||"未知错误"}`),process.exit(1)),o.data}getCmpListByFramework(e){if(!e)return this.cmpList;const t=x(e);return this.cmpList.filter(e=>e.framework===t)}getCmpInfoByCmpType(e){return e&&this.cmpInfoMap[e]||null}updateCustomCmpList(e){e&&Array.isArray(e)&&(this.cmpList=e,e.forEach(e=>{this.cmpInfoMap[e.cmpType]=e}))}async request(e,t,s={}){const o=await this.ensureValidToken(),{data:i,headers:n={},params:r}=s,a=this.buildFullUrl(t);try{const t=await l({method:e,url:a,data:i,params:r,headers:{Authorization:`Bearer ${o}`,"xsy-inner-source":"bff",...n}});if(t.data&&t.data.code&&200!==t.data.code)throw new Error(`请求失败: ${t.data.message||"未知错误"}`);return t.data}catch(s){throw A(`请求失败 [${e} ${t}]: ${s.message}`),s.response&&A(`响应数据: ${JSON.stringify(s.response.data)}`),s}}async get(e,t={}){return await this.request("GET",e,t)}async post(e,t={}){return await this.request("POST",e,t)}async put(e,t={}){return await this.request("PUT",e,t)}async delete(e,t={}){return await this.request("DELETE",e,t)}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("axios"),t=require("form-data"),s=require("node:fs"),o=require("node:path"),i=require("ora"),n=require("lodash"),r=require("akfun"),a=require("./neoLogin.js"),c=require("../utils/projectUtils/updatePublishLog.js"),u=require("../utils/common.js");var h,p;exports.__require=function(){if(p)return h;p=1;const l=e,d=t,m=s,f=o,y=i,w=n,{resolve:g}=r,k=a.__require(),$=c.__require(),{getFramework:x,errorLog:A,successLog:C}=u.__require(),T="https://crm.xiaoshouyi.com",F="https://login-cd.xiaoshouyi.com/auc/oauth2/auth",L="https://login.xiaoshouyi.com/auc/oauth2/token",b="/rest/metadata/v3.0/ui/customComponents",S="/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent",P="/rest/metadata/v3.0/ui/components/filter?custom=true",U=e=>`/rest/metadata/v3.0/ui/customComponents/${e}/codeLib`,B="/rest/metadata/v3.0/ui/customComponents/actions/upload",E=["cmpType","label","componentCategory","description","framework","icon","iconUrl","orderNo","version","propsSchema","defaultProps","previewProps","events","functions","asset","modelAsset","cssAsset","codeLib"];return h=class{constructor(e={}){const{assetsRoot:t,neoBaseURL:s,tokenAPI:o,loginURL:i,auth:n,authType:r}=e||{};this.authType=r||"oauth2","password"!==this.authType||n||(A("密码授权模式时,neo.config.js / neoConfig / auth 配置不能为空"),process.exit(1)),"password"===this.authType?n.client_id&&n.client_secret&&n.username&&n.password||(A("neo.config.js / neoConfig / auth 配置不完整(password 模式),需要包含 client_id、client_secret、username、password"),process.exit(1)):"oauth2"===this.authType?i&&o||(A("neo.config.js / neoConfig 配置不完整(oauth2 模式),需要包含 loginURL、tokenAPI 配置。"),process.exit(1)):(A(`不支持的授权类型: ${this.authType},可选值:oauth2、password`),process.exit(1)),this.assetsRoot=t||g("dist"),this.neoBaseURL=s||T,this.tokenAPI=o||L,this.loginURL=i||F,this.auth=n,this.cmpList=[],this.cmpInfoMap={},this.tokenCache={token:null,expiresAt:null}}buildFullUrl(e){return e.startsWith("http://")||e.startsWith("https://")?e:`${this.neoBaseURL}${e}`}uploadAPI(){return this.buildFullUrl(B)}saveAPI(){return this.buildFullUrl(S)}isTokenExpired(){return!this.tokenCache.token||!this.tokenCache.expiresAt||Date.now()>=this.tokenCache.expiresAt}async getToken(){return this.isTokenExpired()?"oauth2"===this.authType?await this.getTokenByOAuth2():await this.getTokenByPassword():this.tokenCache.token}async getTokenByPassword(){const e=y("获取 token(密码模式)...").start();if(!this.isTokenExpired())return C("使用缓存的 token。",e),this.tokenCache.token;const t=new URLSearchParams;t.append("grant_type","password"),t.append("client_id",this.auth.client_id),t.append("client_secret",this.auth.client_secret),t.append("username",this.auth.username),t.append("password",this.auth.password);const s=this.buildFullUrl(this.tokenAPI);try{const o=await l.post(s,t.toString(),{headers:{"Content-Type":"application/x-www-form-urlencoded"}}),i=o.data||{},{access_token:n,expires_in:r}=i;n||(A("获取 token 失败(授权配置错误):响应中未包含 access_token,"+JSON.stringify(o.data),e),process.exit(1));const a=parseInt(r)||3600;return this.tokenCache={...i,token:n,expiresAt:Date.now()+1e3*(a-60)},e.clear(),e.stop(),n}catch(o){A("获取 token 失败",e),A(`\n获取 token 失败: ${o.message||o.msg}`),A(`\ntoken 授权地址: ${s}`),A(`\ntoken 请求参数: ${t}`),o.response&&A(`响应数据: ${JSON.stringify(o.response.data)}`),process.exit(1)}}async getTokenByOAuth2(){const e=y("获取 token(OAuth2 模式)...").start();try{const t={loginURL:this.loginURL,tokenAPI:this.tokenAPI},s=new k(t),o=await s.getAccessToken(),i=o.access_token;return this.tokenCache={...o,token:i,expiresAt:Date.now()+72e5},e.clear(),e.stop(),i}catch(t){A("获取 token 失败(OAuth2 模式)",e),A(`\n获取 token 失败: ${t.message||t.msg}`),t.response&&A(`响应数据: ${JSON.stringify(t.response.data)}`),process.exit(1)}}async refreshToken(){return this.tokenCache={token:null,expiresAt:null},await this.getToken()}async ensureValidToken(){if(!this.tokenCache.token)return await this.getToken();if(this.isTokenExpired()){const e=y("token 已过期,正在刷新...").start();try{const t=await this.refreshToken();return C("token 刷新成功。",e),t}catch(t){throw A("token 刷新失败。",e),t}}return this.tokenCache.token}async uploadFile(e,t={}){const s=await this.ensureValidToken();if(!e||"string"!=typeof e)throw new Error(`文件路径无效: ${e}`);if(!m.existsSync(e))throw new Error(`文件不存在: ${e}`);const o=m.statSync(e);if(!o.isFile())throw new Error(`路径不是文件: ${e}`);const i=t.maxSize||5242880;if(o.size>i){const e=(o.size/1024/1024).toFixed(2),t=(i/1024/1024).toFixed(2);throw new Error(`文件大小超过限制: ${e}MB > ${t}MB`)}if(0===o.size)throw new Error(`文件为空: ${e}`);const n=f.basename(e),r=(o.size/1024).toFixed(2),a=y(`正在上传文件: ${n} (${r}KB)...`).start();try{const o=new d,i=t.fieldName||"customComponentCode",r=m.createReadStream(e);o.append(i,r,n);const c=this.uploadAPI(),u=t.timeout||6e4,h={headers:{Authorization:`Bearer ${s}`,"xsy-inner-source":"bff",...o.getHeaders()},timeout:u,maxContentLength:1/0,maxBodyLength:1/0},p=await l.post(c,o,h);let f;const y=p.data;if(200!==p.status&&201!==p.status)throw new Error(`上传失败: HTTP ${p.status}`);if("string"==typeof y)f=y.trim();else{if(!y||"object"!=typeof y)throw new Error("响应数据格式不正确: "+typeof y);if(void 0!==y.code&&200!==y.code&&0!==y.code){const e=y.message||y.msg||"未知错误";throw new Error(`上传失败: ${e} (code: ${y.code})`)}f=void 0!==y.data?y.data:void 0!==y.url?y.url:void 0!==y.fileUrl?y.fileUrl:y}if(!f)throw new Error("返回的文件地址为空");let w;return"string"==typeof f?w=f:f&&"object"==typeof f&&f.url&&(w=f.url),C(`文件上传成功: ${n} -> ${w}`,a),w}catch(t){if(A(`上传文件失败: ${t.message||t.msg}, 文件路径: ${e}`,a),t.response){const e=t.response.status,s=t.response.statusText,o=t.response.data,i=t.config?.url||this.uploadAPI();if(A("\n========== 上传请求详情 =========="),A(`请求 URL: ${i}`),A(`HTTP 状态码: ${e} ${s}`),A(`响应数据: ${JSON.stringify(o)}`),A("==================================\n"),404===e)throw new Error(`上传 API 不存在 (404): ${i}\n请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n当前配置的 API 路径: ${B}`)}else t.request&&A("请求已发送但未收到响应,请检查网络连接或代理配置。");throw t}}async publish2oss(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e},o=m.readdirSync(this.assetsRoot).map(async o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;try{const e=await this.uploadFile(i);o.indexOf("Model")>-1?s.modelAsset=e:o.endsWith(".css")?s.cssAsset=e:o.endsWith(".zip")?s.codeLib=e:s.asset=e}catch(e){A(`文件上传失败(${o}):\n`),process.exit(1)}}});return await Promise.all(o),s&&s.cmpType&&(console.info("上传至 OSS 的文件信息:\n",s),$(s)),s}async getCmpAssets(e,t=[".js",".css",".zip"]){if(!e)return void A(`自定义组件名称不能为空: ${e}`);if(!m.existsSync(this.assetsRoot))return void A(`未找到自定义组件资源目录: ${this.assetsRoot}`);const s={cmpType:e};return m.readdirSync(this.assetsRoot).forEach(o=>{const i=f.join(this.assetsRoot,o),n=m.statSync(i),r=f.parse(i);if(n.isFile()&&t.includes(r.ext)){let t=w.camelCase(e);if(o.indexOf(t)<0)return;const r=5242880;if(n.size>r){const e=(n.size/1024/1024).toFixed(2),t=(r/1024/1024).toFixed(2);throw new Error(`${o} 文件大小超过限制: ${e}MB > ${t}MB`)}const a={fileContent:m.createReadStream(i),fileName:o,fileSize:n.size};o.indexOf("Model")>-1?s.modelAssetFile=a:o.endsWith(".css")?s.cssAssetFile=a:o.endsWith(".zip")?s.codeLibFile=a:s.assetFile=a}}),s}async updateCustomComponent(e){const t=await this.ensureValidToken();if(!e)throw new Error("componentData 不能为空");const s=y("正在保存自定义组件信息...").start();try{const o=this.saveAPI(),i=new d;e.assetFile&&i.append("assetFile",e.assetFile.fileContent,e.assetFile.fileName),e.modelAssetFile&&i.append("modelAssetFile",e.modelAssetFile.fileContent,e.modelAssetFile.fileName),e.cssAssetFile&&i.append("cssAssetFile",e.cssAssetFile.fileContent,e.cssAssetFile.fileName),e.codeLibFile&&i.append("codeLibFile",e.codeLibFile.fileContent,e.codeLibFile.fileName),i.append("component",JSON.stringify(w.omit(e,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])));const n=await l.post(o,i,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff",...i.getHeaders()},timeout:12e4,maxContentLength:1/0,maxBodyLength:1/0}),{code:r,message:a,msg:c}=n.data||{};r&&200!==r&&(A(`保存自定义组件信息失败: ${a||c||"未知错误"}`),process.exit(1)),s.clear(),s.stop()}catch(e){const t=e.message||e.msg;A(t?`保存自定义组件信息失败: ${t}`:`保存自定义组件信息失败: ${JSON.stringify(e)}`,s),process.exit(1)}}async getCustomCmpList(){const e=await this.ensureValidToken();try{let t=this.buildFullUrl(P);t+=`&fields=${E.join(",")}`;const s=await l.get(t,{headers:{Authorization:`Bearer ${e}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:o,message:i}=s.data||{};o&&200!==o&&(A(`获取自定义组件列表失败: ${i||"未知错误"}`),process.exit(1)),this.updateCustomCmpList(s.data.data||[])}catch(e){const t=e.message||e.msg;A(t?`获取自定义组件列表失败: ${t}`:`响应数据: ${JSON.stringify(e)}`),process.exit(1)}return this.cmpList||[]}getCodeLibByCmpType(e){return e?this.buildFullUrl(U(e)):null}async deleteCmp(e){const t=await this.ensureValidToken();e||(A("自定义组件名称不能为空。"),process.exit(1));let s=this.buildFullUrl(b);s+=`/${e}`;const o=await l.delete(s,{headers:{Authorization:`Bearer ${t}`,"xsy-inner-source":"bff","Content-Type":"application/json"}}),{code:i,message:n}=o.data||{};return i&&200!==i&&(A(`删除自定义组件失败: ${n||"未知错误"}`),process.exit(1)),o.data}getCmpListByFramework(e){if(!e)return this.cmpList;const t=x(e);return this.cmpList.filter(e=>e.framework===t)}getCmpInfoByCmpType(e){return e&&this.cmpInfoMap[e]||null}updateCustomCmpList(e){e&&Array.isArray(e)&&(this.cmpList=e,e.forEach(e=>{this.cmpInfoMap[e.cmpType]=e}))}async request(e,t,s={}){const o=await this.ensureValidToken(),{data:i,headers:n={},params:r}=s,a=this.buildFullUrl(t);try{const t=await l({method:e,url:a,data:i,params:r,headers:{Authorization:`Bearer ${o}`,"xsy-inner-source":"bff",...n}});if(t.data&&t.data.code&&200!==t.data.code)throw new Error(`请求失败: ${t.data.message||t.data.msg||"未知错误"}`);return t.data}catch(s){throw A(`请求失败 [${e} ${t}]: ${s.message||s.msg}`),s.response&&A(`响应数据: ${JSON.stringify(s.response.data)}`),s}}async get(e,t={}){return await this.request("GET",e,t)}async post(e,t={}){return await this.request("POST",e,t)}async put(e,t={}){return await this.request("PUT",e,t)}async delete(e,t={}){return await this.request("DELETE",e,t)}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),require("lodash");const e=require("akfun"),r=require("ora"),t=require("./neoService.js"),o=require("../utils/common.js"),i=require("../utils/pathUtils.js"),s=require("../utils/cmpUtils/getCmpTypeByDir.js"),n=require("../utils/cmpUtils/createCmpByZip.js");var c,u;exports.__require=function(){if(u)return c;u=1;const{getConfigObj:a}=e,p=r,m=t.__require(),{getFramework:f,errorLog:g,successLog:l}=o.__require(),{catchCurPackageJson:q}=i.__require(),C=s.__require(),_=n.__require(),y=f(a(q()).framework);return c=async(e,r,t)=>{if(!r)return void g("未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。");C().indexOf(e)>-1&&(g(`当前项目目录中已存在${e}自定义组件。(./src/components 目录下)`),process.exit(1));const o=p("正在拉取组件...").start();try{let i=t,s=[],n={},c=null;t?(s=t.cmpList||[],n=t.cmpInfoMap||{}):(i=new m(r),o.info("正在获取自定义组件列表..."),s=await i.getCustomCmpList(),n=i.cmpInfoMap||{}),0===s.length&&(g("拉取失败,当前租户暂无任何自定义组件。",o),process.exit(1)),c=i.getCmpInfoByCmpType(e),c||(g(`拉取失败,当前租户不存在${e}自定义组件。`,o),process.exit(1)),c.framework&&c.framework!==y&&(g(`拉取失败,${e}自定义组件与当前项目技术栈不一致。`,o),process.exit(1));const u=i.getCodeLibByCmpType(e),a=await i.ensureValidToken();await _(u,{token:a,cmpName:e,componentBaseDir:"./src/components"})||(g(`拉取失败,${e}自定义组件源码解析失败,请检查源码文件是否正确。`,o),process.exit(1)),l(`已成功拉取${e}自定义组件!\n`,o)}catch(e){throw g(`拉取自定义组件失败: ${e.message}`,o),e}},c};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),require("lodash");const e=require("akfun"),r=require("ora"),t=require("./neoService.js"),o=require("../utils/common.js"),s=require("../utils/pathUtils.js"),i=require("../utils/cmpUtils/getCmpTypeByDir.js"),n=require("../utils/cmpUtils/createCmpByZip.js");var c,u;exports.__require=function(){if(u)return c;u=1;const{getConfigObj:a}=e,p=r,m=t.__require(),{getFramework:g,errorLog:f,successLog:l}=o.__require(),{catchCurPackageJson:q}=s.__require(),C=i.__require(),_=n.__require(),y=g(a(q()).framework);return c=async(e,r,t)=>{if(!r)return void f("未找到 NeoCRM 平台授权配置(neo.config.js / authConfig)。");C().indexOf(e)>-1&&(f(`当前项目目录中已存在${e}自定义组件。(./src/components 目录下)`),process.exit(1));const o=p("正在拉取组件...").start();try{let s=t,i=[],n={},c=null;t?(i=t.cmpList||[],n=t.cmpInfoMap||{}):(s=new m(r),o.info("正在获取自定义组件列表..."),i=await s.getCustomCmpList(),n=s.cmpInfoMap||{}),0===i.length&&(f("拉取失败,当前租户暂无任何自定义组件。",o),process.exit(1)),c=s.getCmpInfoByCmpType(e),c||(f(`拉取失败,当前租户不存在${e}自定义组件。`,o),process.exit(1)),c.framework&&c.framework!==y&&(f(`拉取失败,${e}自定义组件与当前项目技术栈不一致。`,o),process.exit(1));const u=s.getCodeLibByCmpType(e),a=await s.ensureValidToken();await _(u,{token:a,cmpName:e,componentBaseDir:"./src/components"})||(f(`拉取失败,${e}自定义组件源码解析失败,请检查源码文件是否正确。`,o),process.exit(1)),l(`已成功拉取${e}自定义组件!\n`,o)}catch(e){throw f(`拉取自定义组件失败: ${e.message||e.msg}`,o),e}},c};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:fs"),t=require("node:path"),s=require("lodash"),o=require("akfun"),r=require("ora"),a=require("./neoService.js"),i=require("../utils/common.js"),n=require("../utils/pathUtils.js"),c=require("../utils/projectUtils/createCmpProjectZip.js");var l,p;exports.__require=function(){if(p)return l;p=1;const u=e,g=t,m=s,{getConfigObj:d}=o,w=r,y=a.__require(),{getFramework:f,errorLog:h,successLog:v}=i.__require(),{catchCurPackageJson:b}=n.__require(),T=c.__require(),C=d(b()),$=(e=[])=>e.map(e=>({label:e.label,description:e.description,propSchema:JSON.stringify(e)})),P=(e=[],t)=>e&&0!==e.length?e.map(e=>({...e,componentType:t,eventCategory:e.eventCategory||2,pageType:e.pageType||1,targetDevice:e.targetDevice||1,eventParams:e.eventParams||[]})):[],q=(e=[],t)=>e&&0!==e.length?e.map(e=>({...e,componentType:t,funcScope:e.funcScope||"all",pageType:e.pageType||1,targetDevice:e.targetDevice||1,custom:void 0===e.custom||e.custom,funcInParams:e.funcInParams||[],funcOutParams:e.funcOutParams||[]})):[];return l=async(e,t)=>{const s=w("正在发布组件...").start();try{let o,r=new y(e);await r.ensureValidToken(),s.start("[1/4] 打包源码文件(含单个自定义组件源码)...");try{o=T(t,process.cwd(),e.assetsRoot),o?v(`[1/4] 源码文件打包完成: ${g.basename(o)}。`,s):h("[1/4] 源码文件打包失败,未返回 zip 文件路径。",s)}catch(e){h("[1/4] 源码文件打包失败。",s)}s.start("[2/4] 获取自定义组件构建产物...");const a=await r.getCmpAssets(t);let i;s.start("[3/4] 构建组件数据...");try{i=await(async(e,t)=>{if(!t||!t.cmpType)return h("自定义组件信息或组件名称不能为空"),null;const{cmpType:s}=t;if(!e||!u.existsSync(e))return h(`未找到自定义组件目录: ${e}`),null;const o=m.camelCase(s),r=g.join(e,`${o}Model.js`),a=globalThis.window;globalThis.window||(globalThis.window={console:console,neoRequire:()=>{},postMessage:()=>{}});try{u.existsSync(r)?require(r):(h(`未找到自定义组件模型文件,请检查以下路径是否存在:${r}`),process.exit(1)),globalThis.window&&globalThis.window.NEOEditorCustomModels||(h(`模型文件未导出有效模型方法(CatchCustomCmpModelClass),模型文件地址: ${r} `),process.exit(1));const e=globalThis.window.NEOEditorCustomModels[s];e||(h(`未找到自定义组件模型类(${s}),模型文件地址: ${r} `),process.exit(1));const o=new e;o||(h(`未找到自定义组件模型信息(${s}),模型文件地址: ${r} `),process.exit(1));const a={...t,version:C.version||"1.0.0",framework:C.framework?f(C.framework):0,label:o.label||s,description:o.description||"",componentCategory:(o.tags||["自定义组件"]).join(","),targetPage:o.targetPage||["customPage"],targetObject:o.targetObject||["all"],targetApplication:o.targetApplication||["all"],targetDevice:o.targetDevice||"all",iconUrl:o.iconUrl||o.iconUrl,defaultProps:JSON.stringify(o.defaultComProps||{}),previewProps:JSON.stringify(o.previewComProps||{}),props:$(o.propsSchema||[]),events:P(o.events||[],s),functions:q(o.functions||o.actions||[],s),exposedToDesigner:void 0===o.exposedToDesigner||o.exposedToDesigner,namespace:o.namespace||"neo-cmp-cli",enableDuplicate:void 0===o.enableDuplicate||o.enableDuplicate};return console.log(`自定义组件模型信息(${s}):`,m.omit(a,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"])),a}catch(e){return h(`自定义组件模型文件解析失败 (${r||"未知路径"}): ${e.message}`),h(e.stack),null}finally{void 0===a?delete globalThis.window:globalThis.window=a}})(e.assetsRoot,a),i?v("[3/4] 组件数据构建完成。",s):h(`[3/4] 未获取到自定义组件模型信息(${t})。`,s)}catch(e){h(`[3/4] 组件数据构建失败: ${e.message}`,s)}s.start("[4/4] 保存组件信息到 NeoCRM 平台...");try{await r.updateCustomComponent(i),v("[4/4] 组件信息保存成功",s)}catch(e){h("[4/4] 组件信息保存失败",s)}const{tenant_id:n,instance_uri:c}=r.tokenCache||{};console.log(`\n✅ 自定义组件发布成功!\n(当前租户 ID: ${n||"未返回"},所在租户的 API 域名: ${c||"未返回"}。)`)}catch(e){try{s&&s.isSpinning&&h(`❌ 自定义组件发布失败: ${e.message}`,s)}catch{h(`\n❌ 自定义组件发布失败: ${e.message}`)}throw e}},l};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:fs"),t=require("node:path"),s=require("lodash"),r=require("akfun"),o=require("ora"),a=require("./neoService.js"),i=require("../utils/common.js"),n=require("../utils/pathUtils.js"),c=require("../utils/projectUtils/createCmpProjectZip.js"),l=require("../utils/projectUtils/updatePublishLog.js");var p,u;exports.__require=function(){if(u)return p;u=1;const g=e,m=t,d=s,{getConfigObj:w}=r,y=o,h=a.__require(),{getFramework:f,errorLog:b,successLog:v}=i.__require(),{catchCurPackageJson:T}=n.__require(),C=c.__require(),q=l.__require(),P=w(T()),$=(e=[])=>e.map(e=>({label:e.label,description:e.description,propSchema:JSON.stringify(e)})),j=(e=[],t)=>e&&0!==e.length?e.map(e=>({...e,componentType:t,eventCategory:e.eventCategory||2,pageType:e.pageType||1,targetDevice:e.targetDevice||1,eventParams:e.eventParams||[]})):[],_=(e=[],t)=>e&&0!==e.length?e.map(e=>({...e,componentType:t,funcScope:e.funcScope||"all",pageType:e.pageType||1,targetDevice:e.targetDevice||1,custom:!0,funcInParams:e.funcInParams||[],funcOutParams:e.funcOutParams||[]})):[];return p=async(e,t)=>{const s=y("正在发布组件...").start();try{let r,o=new h(e);await o.ensureValidToken(),s.start("[1/4] 打包源码文件(含单个自定义组件源码)...");try{r=C(t,process.cwd(),e.assetsRoot),r?v(`[1/4] 源码文件打包完成: ${m.basename(r)}。`,s):b("[1/4] 源码文件打包失败,未返回 zip 文件路径。",s)}catch(e){b("[1/4] 源码文件打包失败。",s)}s.start("[2/4] 获取自定义组件构建产物...");const a=await o.getCmpAssets(t);let i;s.start("[3/4] 构建组件数据...");try{i=await(async(e,t)=>{if(!t||!t.cmpType)return b("自定义组件信息或组件名称不能为空"),null;const{cmpType:s}=t;if(!e||!g.existsSync(e))return b(`未找到自定义组件目录: ${e}`),null;const r=d.camelCase(s),o=m.join(e,`${r}Model.js`),a=globalThis.window;globalThis.window||(globalThis.window={console:console,neoRequire:()=>{},postMessage:()=>{}});try{g.existsSync(o)?require(o):(b(`未找到自定义组件模型文件,请检查以下路径是否存在:${o}`),process.exit(1)),globalThis.window&&globalThis.window.NEOEditorCustomModels||(b(`模型文件未导出有效模型方法(CatchCustomCmpModelClass),模型文件地址: ${o} `),process.exit(1));const e=globalThis.window.NEOEditorCustomModels[s];e||(b(`未找到自定义组件模型类(${s}),模型文件地址: ${o} `),process.exit(1));const r=new e;return r||(b(`未找到自定义组件模型信息(${s}),模型文件地址: ${o} `),process.exit(1)),{...t,version:P.version||"1.0.0",framework:P.framework?f(P.framework):0,label:r.label||s,description:r.description||"",componentCategory:(r.tags||["自定义组件"]).join(","),targetPage:r.targetPage||["customPage"],targetObject:r.targetObject||["all"],targetApplication:r.targetApplication||["all"],targetDevice:r.targetDevice||"all",iconUrl:r.iconUrl||r.iconUrl,defaultProps:JSON.stringify(r.defaultComProps||{}),previewProps:JSON.stringify(r.previewComProps||{}),props:$(r.propsSchema||[]),events:j(r.events||[],s),functions:_(r.functions||r.actions||[],s),exposedToDesigner:void 0===r.exposedToDesigner||r.exposedToDesigner,namespace:r.namespace||"neo-cmp-cli",enableDuplicate:void 0===r.enableDuplicate||r.enableDuplicate}}catch(e){return b(`自定义组件模型文件解析失败 (${o||"未知路径"}): ${e.message||e.msg}`),b(e.stack),null}finally{void 0===a?delete globalThis.window:globalThis.window=a}})(e.assetsRoot,a),i?v("[3/4] 组件数据构建完成。",s):b(`[3/4] 未获取到自定义组件模型信息(${t})。`,s)}catch(e){b(`[3/4] 组件数据构建失败: ${e.message||e.msg}`,s)}s.start("[4/4] 保存组件信息到 NeoCRM 平台..."),q(d.omit(i,["assetFile","modelAssetFile","cssAssetFile","codeLibFile"]));try{await o.updateCustomComponent(i),v("[4/4] 组件信息保存成功",s)}catch(e){b("[4/4] 组件信息保存失败",s)}const{tenant_id:n,instance_uri:c}=o.tokenCache||{};console.log(`\n✅ 自定义组件发布成功!\n(当前租户 ID: ${n||"未返回"},所在租户的 API 域名: ${c||"未返回"}。)`)}catch(e){try{s&&s.isSpinning&&b(`❌ 自定义组件发布失败: ${e.message||e.msg}`,s)}catch{b(`\n❌ 自定义组件发布失败: ${e.message||e.msg}`)}throw e}},p};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("akfun"),s=require("node:fs"),t=require("node:path"),r=require("lodash"),n=require("ora"),c=require("../utils/pathUtils.js"),a=require("../utils/projectUtils/updatePublishLog.js"),i=require("../utils/common.js");var o,u;exports.__require=function(){if(u)return o;u=1;const{aliBOS:l,baiduBOS:d}=e,f=s,$=t,g=r,h=n,{getConfigObj:m}=e,{catchCurPackageJson:y}=c.__require(),b=a.__require(),{errorLog:p,warningLog:w,successLog:S}=i.__require(),j=m(y());async function v(e,s,t,r,n,c){const a=$.basename(s),i=(f.statSync(s).size/1024).toFixed(2),o=h(`正在上传文件: ${a} (${i}KB)...`).start();try{const i=await e.get(t);if(i&&i.url)return o.warn(`文件已存在,跳过上传: ${a}`),{success:!1,status:"文件上传失败",widgetName:c.name,fileName:a,filepath:s,ossPath:i.url,error:"线上存在重名文件。"};const u=await e.upload(t,s),l=((e,s,t)=>{const r={baidu:"bj.bcebos.com",ali:"oss-cn-beijing.aliyuncs.com"}[e];if(!r)throw new Error(`不支持的oss类型: ${e}`);return`https://${s}.${r}/${t}`})(r,n.bucket,t);return S(`文件上传成功: ${a} -> ${l}`,o),{success:!0,status:"文件上传成功",fileName:a,widgetName:c.name,filepath:s,ossPath:l,resultMsg:u}}catch(e){return p(`文件上传失败: ${a}`,o),p("\n========== 上传文件详情 =========="),p(`文件路径: ${s}`),p(`OSS 对象键: ${t}`),p(`错误信息: ${e.message}`),e.stack&&p(`错误堆栈: ${e.stack}`),p("==================================\n"),{success:!1,status:"文件上传失败",widgetName:c.name,fileName:a,filepath:s,error:e.message}}}return o=async(e,s,t,r=[".js",".css"])=>{if("baidu"!==e&&"ali"!==e)return void p(`不支持的oss类型: ${e}`);if(!s)return void p("ossConfig 不能为空");if(!t)return void p("assetsRoot 不能为空");if(!f.existsSync(t))return void p(`assetsRoot 不存在: ${t}`);if(!f.statSync(t).isDirectory())return void p(`assetsRoot 不是目录: ${t}`);const n=((e,s)=>"baidu"===e?new d(s.endpoint,s.bucket,s.AccessKeyId||s.AccessKeyID||s.accessKeyId||s.accessKeyID,s.AccessKeySecret):"ali"===e?new l(s.endpoint,s.bucket,s.AccessKeyId||s.AccessKeyID||s.accessKeyId||s.accessKeyID,s.AccessKeySecret):void 0)(e,s);if(!n)return void p("无法创建 OSS 客户端,请检查 ossType 和 ossConfig 配置");const c=f.readdirSync(t);if(0===c.length)return void w(`构建目录为空: ${t}`);const a=h("正在准备上传文件...").start();try{const i=c.filter(e=>{const s=$.join(t,e);try{if(!f.statSync(s).isFile())return!1;const e=$.parse(s);return r.includes(e.ext)}catch(e){return w(`无法读取文件状态: ${s} - ${e.message}`),!1}});if(0===i.length)return void a.warn("未找到需要上传的文件");S(`找到 ${i.length} 个文件需要上传`,a);const o=i.map(async r=>{const c=$.join(t,r),a=$.parse(c),i=function(e,s=j.version,t=j.name){let r=e.lastIndexOf(".umd");return-1===r&&(r=e.lastIndexOf(".esm")),-1===r&&(r=e.lastIndexOf(".lib")),-1===r&&(r=e.lastIndexOf(".")),-1===r?`${t}/${e}-${s}`:`${t}/${e.substring(0,r)}-${s}${e.substring(r)}`}(r);return await v(n,c,i,e,s,a)}),u=(await Promise.all(o)).filter(e=>void 0!==e),l=(e=>{const s={};return e.forEach(e=>{if(!e||!e.widgetName)return;let t=e.widgetName;const r={cmpType:g.kebabCase(t)};t.includes("Model")?(t=t.replace("Model",""),r.cmpType=g.kebabCase(t),r.modelAsset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`):e.fileName.endsWith(".css")?r.cssAsset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`:r.asset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`,s[t]?s[t]=Object.assign(s[t],r):s[t]=r}),s})(u);l&&Object.keys(l).length>0?(console.info("\n上传至 OSS 的文件信息:\n",l),b(l)):w("未生成有效的文件上传结果");const d=u.filter(e=>e&&e.success).length,h=u.filter(e=>e&&!e.success).length;h>0?w(`\n上传完成:成功 ${d} 个,失败 ${h} 个`):console.info(`\n✅ 所有文件上传成功!共 ${d} 个文件`)}catch(e){throw p("批量上传文件异常",a),p("\n========== 批量上传异常 =========="),p(`错误信息: ${e.message}`),e.stack&&p(`错误堆栈: ${e.stack}`),p("==================================\n"),e}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("akfun"),s=require("node:fs"),t=require("node:path"),r=require("lodash"),n=require("ora"),c=require("../utils/pathUtils.js"),a=require("../utils/projectUtils/updatePublishLog.js"),i=require("../utils/common.js");var o,u;exports.__require=function(){if(u)return o;u=1;const{aliBOS:l,baiduBOS:d}=e,f=s,$=t,g=r,m=n,{getConfigObj:h}=e,{catchCurPackageJson:y}=c.__require(),b=a.__require(),{errorLog:p,warningLog:w,successLog:S}=i.__require(),j=h(y());async function v(e,s,t,r,n,c){const a=$.basename(s),i=(f.statSync(s).size/1024).toFixed(2),o=m(`正在上传文件: ${a} (${i}KB)...`).start();try{const i=await e.get(t);if(i&&i.url)return o.warn(`文件已存在,跳过上传: ${a}`),{success:!1,status:"文件上传失败",widgetName:c.name,fileName:a,filepath:s,ossPath:i.url,error:"线上存在重名文件。"};const u=await e.upload(t,s),l=((e,s,t)=>{const r={baidu:"bj.bcebos.com",ali:"oss-cn-beijing.aliyuncs.com"}[e];if(!r)throw new Error(`不支持的oss类型: ${e}`);return`https://${s}.${r}/${t}`})(r,n.bucket,t);return S(`文件上传成功: ${a} -> ${l}`,o),{success:!0,status:"文件上传成功",fileName:a,widgetName:c.name,filepath:s,ossPath:l,resultMsg:u}}catch(e){return p(`文件上传失败: ${a}`,o),p("\n========== 上传文件详情 =========="),p(`文件路径: ${s}`),p(`OSS 对象键: ${t}`),p(`错误信息: ${e.message||e.msg}`),e.stack&&p(`错误堆栈: ${e.stack}`),p("==================================\n"),{success:!1,status:"文件上传失败",widgetName:c.name,fileName:a,filepath:s,error:e.message||e.msg}}}return o=async(e,s,t,r=[".js",".css"])=>{if("baidu"!==e&&"ali"!==e)return void p(`不支持的oss类型: ${e}`);if(!s)return void p("ossConfig 不能为空");if(!t)return void p("assetsRoot 不能为空");if(!f.existsSync(t))return void p(`assetsRoot 不存在: ${t}`);if(!f.statSync(t).isDirectory())return void p(`assetsRoot 不是目录: ${t}`);const n=((e,s)=>"baidu"===e?new d(s.endpoint,s.bucket,s.AccessKeyId||s.AccessKeyID||s.accessKeyId||s.accessKeyID,s.AccessKeySecret):"ali"===e?new l(s.endpoint,s.bucket,s.AccessKeyId||s.AccessKeyID||s.accessKeyId||s.accessKeyID,s.AccessKeySecret):void 0)(e,s);if(!n)return void p("无法创建 OSS 客户端,请检查 ossType 和 ossConfig 配置");const c=f.readdirSync(t);if(0===c.length)return void w(`构建目录为空: ${t}`);const a=m("正在准备上传文件...").start();try{const i=c.filter(e=>{const s=$.join(t,e);try{if(!f.statSync(s).isFile())return!1;const e=$.parse(s);return r.includes(e.ext)}catch(e){return w(`无法读取文件状态: ${s} - ${e.message||e.msg}`),!1}});if(0===i.length)return void a.warn("未找到需要上传的文件");S(`找到 ${i.length} 个文件需要上传`,a);const o=i.map(async r=>{const c=$.join(t,r),a=$.parse(c),i=function(e,s=j.version,t=j.name){let r=e.lastIndexOf(".umd");return-1===r&&(r=e.lastIndexOf(".esm")),-1===r&&(r=e.lastIndexOf(".lib")),-1===r&&(r=e.lastIndexOf(".")),-1===r?`${t}/${e}-${s}`:`${t}/${e.substring(0,r)}-${s}${e.substring(r)}`}(r);return await v(n,c,i,e,s,a)}),u=(await Promise.all(o)).filter(e=>void 0!==e),l=(e=>{const s={};return e.forEach(e=>{if(!e||!e.widgetName)return;let t=e.widgetName;const r={cmpType:g.kebabCase(t)};t.includes("Model")?(t=t.replace("Model",""),r.cmpType=g.kebabCase(t),r.modelAsset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`):e.fileName.endsWith(".css")?r.cssAsset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`:r.asset=e.success?e.ossPath:`${e.error}[${e.ossPath}]`,s[t]?s[t]=Object.assign(s[t],r):s[t]=r}),s})(u);l&&Object.keys(l).length>0?(console.info("\n上传至 OSS 的文件信息:\n",l),b(l)):w("未生成有效的文件上传结果");const d=u.filter(e=>e&&e.success).length,m=u.filter(e=>e&&!e.success).length;m>0?w(`\n上传完成:成功 ${d} 个,失败 ${m} 个`):console.info(`\n✅ 所有文件上传成功!共 ${d} 个文件`)}catch(e){throw p("批量上传文件异常",a),p("\n========== 批量上传异常 =========="),p(`错误信息: ${e.message||e.msg}`),e.stack&&p(`错误堆栈: ${e.stack}`),p("==================================\n"),e}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var e="1.9.7";const o={version:e};exports.default=o,exports.version=e;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var e="1.9.9";const o={version:e};exports.default=o,exports.version=e;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("webpack-sources");var t,o;require("node:fs"),require("node:path"),exports.__require=function(){if(o)return t;o=1;const{ConcatSource:i}=e;return t=class{key="AddNeoRequirePlugin";constructor(e={}){this.options={verbose:e.verbose||!1,skipInjected:!1!==e.skipInjected,skipExtensions:e.skipExtensions||[".css",".map",".txt",".html"],skipPatterns:e.skipPatterns||[/\.map$/,/\.LICENSE\.txt$/,/\.html$/],...e}}shouldSkipFile(e){for(const t of this.options.skipExtensions)if(e.endsWith(t))return!0;for(const t of this.options.skipPatterns)if(t.test(e))return!0;return!1}isAlreadyInjected(e){return!(!e||"string"!=typeof e)&&(e.includes("NeoCustomCmpFileFactory(window.neoRequire)")&&e.includes("if (!window.neoRequire)"))}isValidFile(e){return!(!e||"string"!=typeof e)&&0!==e.trim().length}log(e,t="info"){if(this.options.verbose||"error"===t){const o="[AddNeoRequirePlugin]";console[t](`${o} ${e}`)}}apply(e){e.hooks.compilation.tap("AddNeoRequirePlugin",e=>{e.hooks.processAssets.tap({name:"AddNeoRequirePlugin",stage:-100},t=>{this.log("开始处理资源文件...");let o=0,i=0,s=0;for(const[n,r]of Object.entries(t))try{if(this.shouldSkipFile(n)){this.log(`跳过文件: ${n} (匹配跳过规则)`),i++;continue}const t=r.source(),s="string"==typeof t?t:t.toString();if(!this.isValidFile(s)){this.log(`跳过文件: ${n} (内容无效)`,"warn"),i++;continue}if(this.options.skipInjected&&this.isAlreadyInjected(s)){this.log(`跳过文件: ${n} (已注入过)`),i++;continue}this.injectNeoRequire(e,n,s),o++,this.log(`成功处理文件: ${n}`)}catch(e){s++,this.log(`处理文件失败: ${n}, 错误: ${e.message}`,"error"),console.error("[AddNeoRequirePlugin] 详细错误:",e)}this.log(`处理完成 - 成功: ${o}, 跳过: ${i}, 错误: ${s}`),s>0&&this.log(`警告: 有 ${s} 个文件处理失败`,"warn")})})}injectNeoRequire(e,t,o){const s=new i("\n(function(NeoCustomCmpFileFactory) {\n if (!window.neoRequire) {\n throw new Error('neoRequire 不存在,请在 NeoCRM 平台中加载此脚本。');\n }\n NeoCustomCmpFileFactory(window.neoRequire);\n})(function(require) {\n ",o,"});");e.updateAsset(t,s)}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("webpack-sources");var t,o;require("node:fs"),require("node:path"),exports.__require=function(){if(o)return t;o=1;const{ConcatSource:i}=e;return t=class{key="AddNeoRequirePlugin";constructor(e={}){this.options={verbose:e.verbose||!1,skipInjected:!1!==e.skipInjected,skipExtensions:e.skipExtensions||[".css",".map",".txt",".html"],skipPatterns:e.skipPatterns||[/\.map$/,/\.LICENSE\.txt$/,/\.html$/],...e}}shouldSkipFile(e){for(const t of this.options.skipExtensions)if(e.endsWith(t))return!0;for(const t of this.options.skipPatterns)if(t.test(e))return!0;return!1}isAlreadyInjected(e){return!(!e||"string"!=typeof e)&&(e.includes("NeoCustomCmpFileFactory(window.neoRequire)")&&e.includes("if (!window.neoRequire)"))}isValidFile(e){return!(!e||"string"!=typeof e)&&0!==e.trim().length}log(e,t="info"){if(this.options.verbose||"error"===t){const o="[AddNeoRequirePlugin]";console[t](`${o} ${e}`)}}apply(e){e.hooks.compilation.tap("AddNeoRequirePlugin",e=>{e.hooks.processAssets.tap({name:"AddNeoRequirePlugin",stage:-100},t=>{this.log("开始处理资源文件...");let o=0,i=0,s=0;for(const[n,r]of Object.entries(t))try{if(this.shouldSkipFile(n)){this.log(`跳过文件: ${n} (匹配跳过规则)`),i++;continue}const t=r.source(),s="string"==typeof t?t:t.toString();if(!this.isValidFile(s)){this.log(`跳过文件: ${n} (内容无效)`,"warn"),i++;continue}if(this.options.skipInjected&&this.isAlreadyInjected(s)){this.log(`跳过文件: ${n} (已注入过)`),i++;continue}this.injectNeoRequire(e,n,s),o++,this.log(`成功处理文件: ${n}`)}catch(e){s++,this.log(`处理文件失败: ${n}, 错误: ${e.message||e.msg}`,"error"),console.error("[AddNeoRequirePlugin] 详细错误:",e)}this.log(`处理完成 - 成功: ${o}, 跳过: ${i}, 错误: ${s}`),s>0&&this.log(`警告: 有 ${s} 个文件处理失败`,"warn")})})}injectNeoRequire(e,t,o){const s=new i("\n(function(NeoCustomCmpFileFactory) {\n if (!window.neoRequire) {\n throw new Error('neoRequire 不存在,请在 NeoCRM 平台中加载此脚本。');\n }\n NeoCustomCmpFileFactory(window.neoRequire);\n})(function(require) {\n ",o,"});");e.updateAsset(t,s)}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:path"),o=require("node:fs"),r=require("./projectUtils/openProject.js");var n,c;exports.__require=function(){if(c)return n;c=1;const s=e,t=o,l=r.__require();return n=function(e,o={}){const{outputShellCommand:r=!0}=o;if(!e)return console.error("运行异常:未找到可用的项目路径。"),!1;const n=s.isAbsolute(e)?e:s.resolve(process.cwd(),e);if(!t.existsSync(n))return console.error(`运行异常:${e} 目录不存在。`),!1;if(!t.statSync(n).isDirectory())return console.error(`运行异常:${e} 不是目录。`),!1;const c=s.relative(process.cwd(),n);let i=!1;try{process.chdir(n),i=!0}catch(e){return console.error(`错误:无法切换到目录 ${c}: ${e.message}`),!1}return r&&(console.log("\n"+"=".repeat(60)),console.log("💡 提示:要切换到新建项目目录,请执行以下命令:"),console.log(`\n cd ${c} \n`),console.log("=".repeat(60)),console.log("\n📝 说明1:组件开发工具(neo-cmp-cli)无法直接改变当前命令窗口工作目录,"),console.log(` 您需要手动执行上述命令才能进入刚创建的自定义组件项目(${c})。`),console.log(`\n📝 说明2:组件开发工具(neo-cmp-cli)默认自动打开编辑器(cursor 或 vscode): neo open -n ${c}。\n`),l("auto",e).catch(e=>{console.error(`自动打开编辑器出错(neo open -n ${c}): ${e.message}`),console.error(`请手动执行命令 neo open -n ${c} 打开编辑器。`)})),i}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("node:path"),o=require("node:fs"),r=require("./projectUtils/openProject.js");var n,s;exports.__require=function(){if(s)return n;s=1;const c=e,t=o,l=r.__require();return n=function(e,o={}){const{outputShellCommand:r=!0}=o;if(!e)return console.error("运行异常:未找到可用的项目路径。"),!1;const n=c.isAbsolute(e)?e:c.resolve(process.cwd(),e);if(!t.existsSync(n))return console.error(`运行异常:${e} 目录不存在。`),!1;if(!t.statSync(n).isDirectory())return console.error(`运行异常:${e} 不是目录。`),!1;const s=c.relative(process.cwd(),n);let i=!1;try{process.chdir(n),i=!0}catch(e){return console.error(`错误:无法切换到目录 ${s}: ${e.message||e.msg}`),!1}return r&&(console.log("\n"+"=".repeat(60)),console.log("💡 提示:要切换到新建项目目录,请执行以下命令:"),console.log(`\n cd ${s} \n`),console.log("=".repeat(60)),console.log("\n📝 说明1:组件开发工具(neo-cmp-cli)无法直接改变当前命令窗口工作目录,"),console.log(` 您需要手动执行上述命令才能进入刚创建的自定义组件项目(${s})。`),console.log(`\n📝 说明2:组件开发工具(neo-cmp-cli)默认自动打开编辑器(cursor 或 vscode): neo open -n ${s}。\n`),l("auto",e).catch(e=>{console.error(`自动打开编辑器出错(neo open -n ${s}): ${e.message||e.msg}`),console.error(`请手动执行命令 neo open -n ${s} 打开编辑器。`)})),i}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),t=require("node:path"),r=require("axios"),s=require("ora"),n=require("adm-zip"),a=require("lodash"),i=require("../neoParams.js"),o=require("./hasCmpTypeByDir.js"),c=require("../projectUtils/hasNeoProject.js"),u=require("../common.js");var f,p;exports.__require=function(){if(p)return f;p=1;const l=e,d=t,m=r,w=s,g=n,y=a,{consoleTag:h}=i.__require(),j=o.__require(),$=c.__require(),{errorLog:q,warningLog:x,successLog:v,parseTsConfigWithTypeScript:b}=u.__require();function _(e,t=0,r=""){const s=" ".repeat(t),n=" ".repeat(t+1);if(null===e)return"null";if(void 0===e)return"undefined";if("string"==typeof e){if(r&&d.isAbsolute(e))try{const t=d.relative(r,e).replace(/\\/g,"/");if(t&&!t.startsWith("..")&&""!==t){const e=t.startsWith(".")?t:"./"+t;return`resolve(${JSON.stringify(e)})`}}catch(e){}return e.includes("resolve(")||e.includes("auth.")?e:JSON.stringify(e)}if("number"==typeof e||"boolean"==typeof e)return String(e);if(Array.isArray(e)){if(0===e.length)return"[]";return"[\n"+e.map(e=>{const s=_(e,t+1,r);return n+s}).join(",\n")+"\n"+s+"]"}if("object"==typeof e){const a=Object.keys(e);if(0===a.length)return"{}";return"{\n"+a.map(s=>{const a=_(e[s],t+1,r);return n+function(e){return function(e){return!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)}(e)?JSON.stringify(e):e}(s)+": "+a}).join(",\n")+"\n"+s+"}"}return String(e)}return f=async function(e,t={}){const{token:r,cmpName:s,componentBaseDir:n="./src/components"}=t||{},a=s;$()||(q(`当前(${process.cwd()})还不是自定义组件项目,请先创建一个自定义组件项目(neo init / neo create project)。`),process.exit(1)),j(a)&&(q(`当前项目已经存在${a}自定义组件。`),process.exit(1));const i=d.join(process.cwd(),".neo-cli","zip-source"),o=w(`${h}正在下载组件源码...`).start();try{await l.ensureDir(i);const t=d.join(i,`${a}.zip`);let s;await l.pathExists(t)&&await l.remove(t);try{s=await m.get(e,{headers:{Authorization:`Bearer ${r}`,"xsy-inner-source":"bff"},responseType:"arraybuffer",timeout:6e4,maxContentLength:1/0,maxBodyLength:1/0,maxRedirects:5,validateStatus:function(e){return e>=200&&e<400}})}catch(e){const t=e.response?`下载文件失败: HTTP ${e.response.status} - ${e.message}`:`下载文件失败: ${e.message}`;throw q(t,o),e}try{let e;e=Buffer.isBuffer(s.data)?s.data:s.data instanceof ArrayBuffer?Buffer.from(s.data):s.data.buffer instanceof ArrayBuffer?Buffer.from(s.data.buffer):Buffer.from(s.data),await l.writeFile(t,e)}catch(e){throw q(`读取组件源码文件失败: ${e.message}`,o),e}o.info(`${h}正在解压组件源码...`);const c=new g(t),u=d.join(i,a);c.extractAllTo(u,!0);const f=d.join(u,n,a);if(!l.existsSync(f))return q(`解压后的 zip 包中未找到 ${a} 组件源码目录。`,o),await l.remove(u),!1;const p=d.resolve(process.cwd(),n,a);await l.ensureDir(p);try{await l.copy(f,p)}catch(e){return q(`自定义组件模板下载失败:${e.message||e}`,o),await l.remove(u),!1}try{const e=n.replace(/^\.\//,"").replace(/\\/g,"/"),t=async(e,r,s)=>{const n=await l.readdir(e);for(const a of n){const n=d.join(e,a),i=await l.stat(n),c=d.basename(n),f=d.relative(u,n),p=f.replace(/\\/g,"/");if(p.startsWith(s+"/")||p===s)continue;const m=d.join(r,f);if(i.isDirectory())await t(n,r,s);else if(i.isFile()){if(await l.pathExists(m)){if("package.json"===c){const e=await l.readJson(n),t=await l.readJson(m),r=y.omit(e.dependencies,Object.keys(t.dependencies)),s=Object.keys(r);s.length>0&&(x(`检测到 package.json 中新增了 ${s.length} 个依赖包:${s.join(", ")}`),x("为确保组件正常运行,请执行以下命令安装依赖:npm install 或 yarn install"));const a=y.merge({},e,t);await l.writeJson(m,a,{spaces:2})}else if("neo.config.js"===c)try{const e=require.resolve(n),t=require.resolve(m);delete require.cache[e],delete require.cache[t];await l.readFile(n,"utf8");const r=await l.readFile(m,"utf8"),s=require(n),a=require(m),i=y.merge({},s,a),o=r.match(/^([\s\S]*?)(module\.exports\s*=\s*\{[\s\S]*\};?\s*)$/);let c="";if(o)c=o[1];else{const e=r.lastIndexOf("module.exports");c=e>0?r.substring(0,e):"'use strict';\nconst path = require('path');\n\n// 统一路径解析\nfunction resolve(dir) {\n return path.resolve(__dirname, dir);\n}\n\n"}const u=d.dirname(m),f=c+"module.exports = "+_(i,0,u)+";\n";await l.writeFile(m,f,"utf8")}catch(e){o.warn(`${h}合并 neo.config.js 配置文件时出现警告:${e.message||e}`)}else if("tsconfig.json"===c)try{const e=b(n);if(await l.pathExists(m)){const t=b(m),r=y.merge({},e,t);await l.writeJson(m,r,{spaces:2})}else await l.writeJson(m,e,{spaces:2})}catch(e){o.warn(`${h}合并 tsconfig.json 配置文件时出现警告:${e.message||e}`)}}else await l.ensureDir(d.dirname(m)),await l.copy(n,m)}}};await t(u,process.cwd(),e)}catch(e){o.warn(`${h}处理源码文件出现警告:${e.message||e}`)}return await l.remove(u),v(`已成功从 zip 包解析自定义组件(${a})!`,o),!0}catch(e){q(`从 zip 包创建自定义组件失败(${a}):${e.message||e}`,o);const t=d.join(i,a);return await l.pathExists(t)&&await l.remove(t),!1}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),t=require("node:path"),r=require("axios"),s=require("ora"),n=require("adm-zip"),a=require("lodash"),i=require("../neoParams.js"),o=require("./hasCmpTypeByDir.js"),c=require("../projectUtils/hasNeoProject.js"),u=require("../common.js");var f,p;exports.__require=function(){if(p)return f;p=1;const l=e,m=t,g=r,d=s,w=n,y=a,{consoleTag:h}=i.__require(),j=o.__require(),$=c.__require(),{errorLog:q,warningLog:x,successLog:v,parseTsConfigWithTypeScript:b}=u.__require();function _(e,t=0,r=""){const s=" ".repeat(t),n=" ".repeat(t+1);if(null===e)return"null";if(void 0===e)return"undefined";if("string"==typeof e){if(r&&m.isAbsolute(e))try{const t=m.relative(r,e).replace(/\\/g,"/");if(t&&!t.startsWith("..")&&""!==t){const e=t.startsWith(".")?t:"./"+t;return`resolve(${JSON.stringify(e)})`}}catch(e){}return e.includes("resolve(")||e.includes("auth.")?e:JSON.stringify(e)}if("number"==typeof e||"boolean"==typeof e)return String(e);if(Array.isArray(e)){if(0===e.length)return"[]";return"[\n"+e.map(e=>{const s=_(e,t+1,r);return n+s}).join(",\n")+"\n"+s+"]"}if("object"==typeof e){const a=Object.keys(e);if(0===a.length)return"{}";return"{\n"+a.map(s=>{const a=_(e[s],t+1,r);return n+function(e){return function(e){return!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(e)}(e)?JSON.stringify(e):e}(s)+": "+a}).join(",\n")+"\n"+s+"}"}return String(e)}return f=async function(e,t={}){const{token:r,cmpName:s,componentBaseDir:n="./src/components"}=t||{},a=s;$()||(q(`当前(${process.cwd()})还不是自定义组件项目,请先创建一个自定义组件项目(neo init / neo create project)。`),process.exit(1)),j(a)&&(q(`当前项目已经存在${a}自定义组件。`),process.exit(1));const i=m.join(process.cwd(),".neo-cli","zip-source"),o=d(`${h}正在下载组件源码...`).start();try{await l.ensureDir(i);const t=m.join(i,`${a}.zip`);let s;await l.pathExists(t)&&await l.remove(t);try{s=await g.get(e,{headers:{Authorization:`Bearer ${r}`,"xsy-inner-source":"bff"},responseType:"arraybuffer",timeout:6e4,maxContentLength:1/0,maxBodyLength:1/0,maxRedirects:5,validateStatus:function(e){return e>=200&&e<400}})}catch(e){const t=e.response?`下载文件失败: HTTP ${e.response.status} - ${e.message||e.msg}`:`下载文件失败: ${e.message||e.msg}`;throw q(t,o),e}try{let e;e=Buffer.isBuffer(s.data)?s.data:s.data instanceof ArrayBuffer?Buffer.from(s.data):s.data.buffer instanceof ArrayBuffer?Buffer.from(s.data.buffer):Buffer.from(s.data),await l.writeFile(t,e)}catch(e){throw q(`读取组件源码文件失败: ${e.message}`,o),e}o.info(`${h}正在解压组件源码...`);const c=new w(t),u=m.join(i,a);c.extractAllTo(u,!0);const f=m.join(u,n,a);if(!l.existsSync(f))return q(`解压后的 zip 包中未找到 ${a} 组件源码目录。`,o),await l.remove(u),!1;const p=m.resolve(process.cwd(),n,a);await l.ensureDir(p);try{await l.copy(f,p)}catch(e){return q(`自定义组件模板下载失败:${e.message||e}`,o),await l.remove(u),!1}try{const e=n.replace(/^\.\//,"").replace(/\\/g,"/"),t=async(e,r,s)=>{const n=await l.readdir(e);for(const a of n){const n=m.join(e,a),i=await l.stat(n),c=m.basename(n),f=m.relative(u,n),p=f.replace(/\\/g,"/");if(p.startsWith(s+"/")||p===s)continue;const g=m.join(r,f);if(i.isDirectory())await t(n,r,s);else if(i.isFile()){if(await l.pathExists(g)){if("package.json"===c){const e=await l.readJson(n),t=await l.readJson(g),r=y.omit(e.dependencies,Object.keys(t.dependencies)),s=Object.keys(r);s.length>0&&(x(`检测到 package.json 中新增了 ${s.length} 个依赖包:${s.join(", ")}`),x("为确保组件正常运行,请执行以下命令安装依赖:npm install 或 yarn install"));const a=y.merge({},e,t);await l.writeJson(g,a,{spaces:2})}else if("neo.config.js"===c)try{const e=require.resolve(n),t=require.resolve(g);delete require.cache[e],delete require.cache[t];await l.readFile(n,"utf8");const r=await l.readFile(g,"utf8"),s=require(n),a=require(g),i=y.merge({},s,a),o=r.match(/^([\s\S]*?)(module\.exports\s*=\s*\{[\s\S]*\};?\s*)$/);let c="";if(o)c=o[1];else{const e=r.lastIndexOf("module.exports");c=e>0?r.substring(0,e):"'use strict';\nconst path = require('path');\n\n// 统一路径解析\nfunction resolve(dir) {\n return path.resolve(__dirname, dir);\n}\n\n"}const u=m.dirname(g),f=c+"module.exports = "+_(i,0,u)+";\n";await l.writeFile(g,f,"utf8")}catch(e){o.warn(`${h}合并 neo.config.js 配置文件时出现警告:${e.message||e.msg||e}`)}else if("tsconfig.json"===c)try{const e=b(n);if(await l.pathExists(g)){const t=b(g),r=y.merge({},e,t);await l.writeJson(g,r,{spaces:2})}else await l.writeJson(g,e,{spaces:2})}catch(e){o.warn(`${h}合并 tsconfig.json 配置文件时出现警告:${e.message||e.msg||e}`)}}else await l.ensureDir(m.dirname(g)),await l.copy(n,g)}}};await t(u,process.cwd(),e)}catch(e){o.warn(`${h}处理源码文件出现警告:${e.message||e.msg||e}`)}return await l.remove(u),v(`已成功从 zip 包解析自定义组件(${a})!`,o),!0}catch(e){q(`从 zip 包创建自定义组件失败(${a}):${e.message||e.msg||e}`,o);const t=m.join(i,a);return await l.pathExists(t)&&await l.remove(t),!1}}};
@@ -1 +1 @@
1
- "use strict";var e,r;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),exports.__require=function(){if(r)return e;function t(e){const r=[];return e&&0!==e.trim().length?(e.length<5&&r.push(`文件名长度必须至少5个字符,当前长度: ${e.length}`),/^[a-zA-Z]/.test(e)||r.push("文件名必须以字母开头"),/^[a-zA-Z][a-zA-Z0-9-]*$/.test(e)||r.push("文件名只能包含字母、数字和连字符(-),且必须以字母开头"),e.includes("--")&&r.push("文件名不能包含连续连字符(--)"),e.endsWith("-")&&r.push("文件名不能以连字符结尾"),{isValid:0===r.length,errors:r}):(r.push("文件名不能为空"),{isValid:!1,errors:r})}return r=1,e={validateProjectName:t,isValidProjectName:function(e){return t(e).isValid},getProjectNameErrors:function(e){return t(e).errors}}};
1
+ "use strict";var e,r;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),exports.__require=function(){if(r)return e;function t(e){const r=[];return e&&0!==e.trim().length?(e.length<2&&r.push(`文件名长度必须至少2个字符,当前长度: ${e.length}`),/^[a-zA-Z]/.test(e)||r.push("文件名必须以字母开头"),/^[a-zA-Z][a-zA-Z0-9-]*$/.test(e)||r.push("文件名只能包含字母、数字和连字符(-),且必须以字母开头"),e.includes("--")&&r.push("文件名不能包含连续连字符(--)"),e.endsWith("-")&&r.push("文件名不能以连字符结尾"),{isValid:0===r.length,errors:r}):(r.push("文件名不能为空"),{isValid:!1,errors:r})}return r=1,e={validateProjectName:t,isValidProjectName:function(e){return t(e).isValid},getProjectNameErrors:function(e){return t(e).errors}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),r=require("node:path"),s=require("adm-zip"),i=require("lodash"),o=require("../neoParams.js"),t=require("./hasNeoProject.js");var n,c;exports.__require=function(){if(c)return n;c=1;const a=e,u=r,l=s,d=i,{consoleTag:f}=o.__require(),p=t.__require();return n=function(e,r,s){const i=r||process.cwd(),o=s||u.join(i,"dist");p(r)||(console.error(`${f}当前目录不是自定义组件项目,请在自定义组件项目目录下执行。`),process.exit(1)),e||(console.error(`${f}自定义组件名称不能为空`),process.exit(1));const t=new l,n=["node_modules",".neo-cli","dist"],c=[".eslintcache","auth.config.js"],y=(r,s="")=>{try{a.readdirSync(r).forEach(i=>{const o=u.join(r,i),l=s?u.join(s,i):i;if(((r,s)=>{const i=u.basename(r),o=a.statSync(r);if(o.isDirectory()&&n.includes(i))return!0;if(o.isFile()&&c.includes(i))return!0;if(s.startsWith("src/components")){const r=u.relative("src/components",s);if(r&&"."!==r&&r.split(u.sep)[0]!==e)return!0}return!1})(o,l))return;const d=a.statSync(o);if(d.isDirectory())y(o,l);else if(d.isFile()){const e=a.readFileSync(o);t.addFile(l,e)}})}catch(e){console.error(`${f}遍历目录失败 (${r}):`,e.message)}};y(i);const m=`${d.camelCase(e)}Source.zip`,j=u.join(o,m);return a.existsSync(j)&&a.removeSync(j),t.writeZip(j),j}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),r=require("node:path"),s=require("adm-zip"),i=require("lodash"),o=require("../neoParams.js"),t=require("./hasNeoProject.js");var n,c;exports.__require=function(){if(c)return n;c=1;const a=e,u=r,l=s,d=i,{consoleTag:f}=o.__require(),p=t.__require();return n=function(e,r,s){const i=r||process.cwd(),o=s||u.join(i,"dist");p(r)||(console.error(`${f}当前目录不是自定义组件项目,请在自定义组件项目目录下执行。`),process.exit(1)),e||(console.error(`${f}自定义组件名称不能为空`),process.exit(1));const t=new l,n=["node_modules",".neo-cli","dist"],c=[".eslintcache","auth.config.js"],m=(r,s="")=>{try{a.readdirSync(r).forEach(i=>{const o=u.join(r,i),l=s?u.join(s,i):i;if(((r,s)=>{const i=u.basename(r),o=a.statSync(r);if(o.isDirectory()&&n.includes(i))return!0;if(o.isFile()&&c.includes(i))return!0;if(s.startsWith("src/components")){const r=u.relative("src/components",s);if(r&&"."!==r&&r.split(u.sep)[0]!==e)return!0}return!1})(o,l))return;const d=a.statSync(o);if(d.isDirectory())m(o,l);else if(d.isFile()){const e=a.readFileSync(o);t.addFile(l,e)}})}catch(e){console.error(`${f}遍历目录失败 (${r}):`,e.message||e.msg)}};m(i);const y=`${d.camelCase(e)}Source.zip`,j=u.join(o,y);return a.existsSync(j)&&a.removeSync(j),t.writeZip(j),j}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),s=require("node:path");var t,r;exports.__require=function(){if(r)return t;r=1;const c=e,a=s;function n(e,s,t){try{if(!c.existsSync(e))return{success:!1,message:`目录不存在: ${e}`};if(!c.statSync(e).isDirectory())return{success:!1,message:`指定路径不是目录: ${e}`};const r=a.join(e,"package.json");if(!c.existsSync(r))return{success:!1,message:`package.json文件不存在: ${r}`};let n=c.readFileSync(r,"utf8");if(!n.includes(s))return{success:!0,message:`package.json中未找到要替换的字符串: ${s}`,filePath:r,replaced:!1};const u=n.replace(new RegExp(s,"g"),t);if(n===u)return{success:!0,message:"替换后内容无变化",filePath:r,replaced:!1};c.writeFileSync(r,u,"utf8");const i=n.match(new RegExp(s,"g"));return{success:!0,message:`成功替换 ${i?i.length:0} 处字符串`,filePath:r,replaced:!0}}catch(e){return{success:!1,message:`replaceInPackage 运行失败: ${e.message}`}}}return t={replaceInPackage:n,replaceInMultiplePackages:function(e,s,t){const r=e.map(e=>({dir:e,result:n(e,s,t)})),c=r.filter(e=>e.result.success).length,a=r.length-c;return{total:e.length,success:c,failed:a,results:r}},validatePackageJson:function(e){try{const s=c.readFileSync(e,"utf8");return JSON.parse(s),{valid:!0}}catch(e){return{valid:!1,error:`JSON格式错误: ${e.message}`}}}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),s=require("node:path");var t,r;exports.__require=function(){if(r)return t;r=1;const c=e,a=s;function n(e,s,t){try{if(!c.existsSync(e))return{success:!1,message:`目录不存在: ${e}`};if(!c.statSync(e).isDirectory())return{success:!1,message:`指定路径不是目录: ${e}`};const r=a.join(e,"package.json");if(!c.existsSync(r))return{success:!1,message:`package.json文件不存在: ${r}`};let n=c.readFileSync(r,"utf8");if(!n.includes(s))return{success:!0,message:`package.json中未找到要替换的字符串: ${s}`,filePath:r,replaced:!1};const u=n.replace(new RegExp(s,"g"),t);if(n===u)return{success:!0,message:"替换后内容无变化",filePath:r,replaced:!1};c.writeFileSync(r,u,"utf8");const i=n.match(new RegExp(s,"g"));return{success:!0,message:`成功替换 ${i?i.length:0} 处字符串`,filePath:r,replaced:!0}}catch(e){return{success:!1,message:`replaceInPackage 运行失败: ${e.message||e.msg}`}}}return t={replaceInPackage:n,replaceInMultiplePackages:function(e,s,t){const r=e.map(e=>({dir:e,result:n(e,s,t)})),c=r.filter(e=>e.result.success).length,a=r.length-c;return{total:e.length,success:c,failed:a,results:r}},validatePackageJson:function(e){try{const s=c.readFileSync(e,"utf8");return JSON.parse(s),{valid:!0}}catch(e){return{valid:!1,error:`JSON格式错误: ${e.message||e.msg}`}}}}};
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),s=require("node:path");var r,t;exports.__require=function(){if(t)return r;t=1;const n=e,c=s;function a(e,s="1.0.0"){try{if(!n.existsSync(e))return{success:!1,message:`目录不存在: ${e}`};if(!n.statSync(e).isDirectory())return{success:!1,message:`指定路径不是目录: ${e}`};const r=c.join(e,"package.json");if(!n.existsSync(r))return{success:!1,message:`package.json文件不存在: ${r}`};const t=n.readFileSync(r,"utf8");let a={};try{a=JSON.parse(t)}catch(e){return{success:!1,message:`package.json 文件解析失败: ${e.message}。`}}const i=a.version||"未定义";return a.version===s?{success:!0,message:`package.json 版本号已经是 ${s}`,filePath:r,oldVersion:i,newVersion:s}:(a.version=s,n.writeFileSync(r,JSON.stringify(a,null,2)+"\n","utf8"),{success:!0,message:`已将 package.json 版本号从 ${i} 重置为 ${s}`,filePath:r,oldVersion:i,newVersion:s})}catch(e){return{success:!1,message:`resetPackageVersion 运行失败: ${e.message}`}}}return r={resetPackageVersion:a,resetVersionInMulPackages:function(e,s="1.0.0"){const r=e.map(e=>({dir:e,result:a(e,s)})),t=r.filter(e=>e.result.success).length,n=r.length-t;return{total:e.length,success:t,failed:n,results:r}}}};
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("fs-extra"),s=require("node:path");var r,t;exports.__require=function(){if(t)return r;t=1;const n=e,c=s;function a(e,s="1.0.0"){try{if(!n.existsSync(e))return{success:!1,message:`目录不存在: ${e}`};if(!n.statSync(e).isDirectory())return{success:!1,message:`指定路径不是目录: ${e}`};const r=c.join(e,"package.json");if(!n.existsSync(r))return{success:!1,message:`package.json文件不存在: ${r}`};const t=n.readFileSync(r,"utf8");let a={};try{a=JSON.parse(t)}catch(e){return{success:!1,message:`package.json 文件解析失败: ${e.message||e.msg}。`}}const i=a.version||"未定义";return a.version===s?{success:!0,message:`package.json 版本号已经是 ${s}`,filePath:r,oldVersion:i,newVersion:s}:(a.version=s,n.writeFileSync(r,JSON.stringify(a,null,2)+"\n","utf8"),{success:!0,message:`已将 package.json 版本号从 ${i} 重置为 ${s}`,filePath:r,oldVersion:i,newVersion:s})}catch(e){return{success:!1,message:`resetPackageVersion 运行失败: ${e.message||e.msg}`}}}return r={resetPackageVersion:a,resetVersionInMulPackages:function(e,s="1.0.0"){const r=e.map(e=>({dir:e,result:a(e,s)})),t=r.filter(e=>e.result.success).length,n=r.length-t;return{total:e.length,success:t,failed:n,results:r}}}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neo-cmp-cli",
3
- "version": "1.9.7",
3
+ "version": "1.9.9",
4
4
  "description": "Neo 自定义组件开发工具,支持react 和 vue2.0技术栈。",
5
5
  "keywords": [
6
6
  "neo-cli",
@@ -42,7 +42,7 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "adm-zip": "^0.5.10",
45
- "akfun": "^5.2.5",
45
+ "akfun": "^5.2.12",
46
46
  "axios": "^0.27.2",
47
47
  "babel-plugin-import": "^1.13.8",
48
48
  "chalk": "^4.0.0",
@@ -0,0 +1,469 @@
1
+ # ComTree 生成过程分析
2
+
3
+ ## 一、概述
4
+
5
+ ComTree 是 Neo UI 框架中元数据能力的载体,负责元数据的加载、解析,基于模型的扩展的加载、解析、合并。它是一个树形结构,每个节点都是一个 `Com` 实例,代表一个组件或布局。
6
+
7
+ ## 二、核心概念
8
+
9
+ ### 2.1 Com 类
10
+ - `Com` 是树形节点,任何一个 com 都可以向下展开
11
+ - Com 是整个元数据实现的骨架,组合 kernel 中的能力构建出立体元数据的解析执行运行时
12
+ - Com 继承自 `XNode`,具备树形结构的基本能力
13
+
14
+ ### 2.2 节点类型
15
+ - **PageCom**: 页面级别的 Com,是整个页面的根节点
16
+ - **LayoutCom**: 布局 Com,负责管理子组件的布局
17
+ - **DataServiceCom**: 数据服务 Com,负责数据获取和管理
18
+ - **普通 Com**: 业务组件 Com
19
+
20
+ ### 2.3 生命周期阶段
21
+ ```typescript
22
+ enum LifePhase {
23
+ INIT = 0, // 初始化
24
+ ATTACHED = 1, // 已挂载到树
25
+ READY = 2, // 准备就绪
26
+ DETACHED = 3, // 已卸载
27
+ DESTROYED = 4 // 已销毁
28
+ }
29
+ ```
30
+
31
+ ## 三、ComTree 生成流程
32
+
33
+ ### 3.1 整体流程
34
+
35
+ ```
36
+ 1. 页面打开请求
37
+
38
+ 2. 创建 PageCom 实例
39
+
40
+ 3. 创建 PageStore (数据服务)
41
+
42
+ 4. Store 加载布局数据 (layoutData)
43
+
44
+ 5. 调用 $expandSubTree 展开子树
45
+
46
+ 6. 递归创建子 Com 节点
47
+
48
+ 7. 应用扩展 (AgentCom)
49
+
50
+ 8. 设置变量空间
51
+
52
+ 9. 标记 ready2render = true
53
+
54
+ 10. 渲染到 UI
55
+ ```
56
+
57
+ ### 3.2 详细步骤
58
+
59
+ #### 步骤 1: 页面打开
60
+
61
+ 在 `NeoRenderer` 或 `PageModelRender` 中,通过以下方式打开页面:
62
+
63
+ ```typescript
64
+ // packages/neo-ui-common/src/_comTreeDom/pageModelRender.tsx
65
+ this.pageCom = NeoApp.openPageByPageInfo({
66
+ pageKey,
67
+ pageEngine,
68
+ cmpType: pageKey,
69
+ pageParams: queryObject
70
+ })
71
+ ```
72
+
73
+ #### 步骤 2: 创建 PageCom 实例
74
+
75
+ ```typescript
76
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom.ts
77
+ class PageCom extends Com {
78
+ constructor(comArgs: ComArgs<IPageConfig>) {
79
+ super(comArgs)
80
+ this[SCOPE] = { page: this } as ComScopeNode
81
+ this.config = comArgs.props as IPageConfig
82
+ SystemCtx.initPagePrivateScope(this)
83
+ }
84
+ }
85
+ ```
86
+
87
+ #### 步骤 3: 创建 Store
88
+
89
+ 在 `Com` 构造函数中,通过 `queueMicrotask` 异步创建 Store:
90
+
91
+ ```typescript
92
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/com.ts:294-296
93
+ queueMicrotask(() => {
94
+ this.$tryCreateStore()
95
+ })
96
+ ```
97
+
98
+ PageCom 重写了 `$tryCreateStore` 方法:
99
+
100
+ ```typescript
101
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom.ts:182-195
102
+ async $tryCreateStore() {
103
+ const { pageEngine, pageKey } = this.props || {}
104
+ const storeCls = CmpStoreRegister.getStoreClass(this.cmpType)
105
+ || CmpStoreRegister.getBasePageStoreClass()
106
+ const store = new storeCls(this)
107
+ this[BOUNDED].boundStore = store
108
+ this[STATE].storeResolved = true
109
+ await store.init()
110
+ store.status = 'init'
111
+ }
112
+ ```
113
+
114
+ #### 步骤 4: 启动数据服务
115
+
116
+ 在表单页面中,通过 `dataServiceStart` 方法启动数据服务:
117
+
118
+ ```typescript
119
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom/formPageUniCom.ts:178-246
120
+ async dataServiceStart(initProps: any = {}) {
121
+ // 1. 应用页面扩展
122
+ await AgentComManager.applyPageAgent(this)
123
+
124
+ // 2. 加载布局数据
125
+ let layoutData = await this.$store.loadLayout()
126
+
127
+ // 3. 权限检查
128
+ let checkAccess = await this.preRenderCheck(...)
129
+
130
+ // 4. 构建 ComTree
131
+ if (layoutData?.layout !== null) {
132
+ let cmp = layoutData.layout
133
+ await this.$expandSubTree([cmp])
134
+
135
+ // 5. 应用扩展
136
+ this.applyAgentCom()
137
+ this.setupVarSpace()
138
+ this.comsReady = true
139
+ }
140
+ }
141
+ ```
142
+
143
+ #### 步骤 5: 展开子树 ($expandSubTree)
144
+
145
+ 这是 ComTree 生成的核心方法:
146
+
147
+ ```typescript
148
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/com.ts:1586-1617
149
+ $expandSubTree(subCmps: ComArgs[]) {
150
+ // 校验逻辑
151
+ if (!subCmps || subCmps.length === 0) {
152
+ this.children = []
153
+ lifecycleInvoking(this, 'ready')
154
+ return
155
+ }
156
+
157
+ // 递归展开
158
+ subCmps.forEach((cmp) => {
159
+ // 1. 根据 cmpType 查找对应的 Com 类
160
+ let ComClass = ComFinder.getCom({ cmpType: cmp.cmpType })
161
+
162
+ // 2. 创建子 Com 实例
163
+ let childCom = new ComClass(cmp)
164
+
165
+ // 3. 将子节点添加到当前节点
166
+ this.$appendChild(childCom)
167
+
168
+ // 4. 如果还有子节点,递归展开
169
+ if (cmp.subCmps && cmp.subCmps.length) {
170
+ childCom.$expandSubTree(cmp.subCmps)
171
+ } else {
172
+ // 5. 没有子节点,标记为 READY
173
+ childCom.$phaseShift(LifePhase.READY, true)
174
+ }
175
+ })
176
+
177
+ // 6. 当前节点标记为 READY
178
+ lifecycleInvoking(this, 'ready')
179
+ }
180
+ ```
181
+
182
+ #### 步骤 6: 添加子节点 ($appendChild)
183
+
184
+ ```typescript
185
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/com.ts:1310-1335
186
+ $appendChild(child: Com) {
187
+ // 1. 如果存在旧关系,先解除
188
+ const lastPCom = child.pCom
189
+ if (lastPCom) {
190
+ lastPCom.$removeChild(child)
191
+ }
192
+
193
+ // 2. 设计态下创建布局事件
194
+ if (InnerApi.isDesignMode()) {
195
+ InnerApi.autoCreateComTreeLayoutEvent(this)
196
+ }
197
+
198
+ // 3. 建立父子关系
199
+ child.pCom = this
200
+ this.children.push(child)
201
+ this.$$linkComCtx(child)
202
+
203
+ // 4. 重新生成 orderNo
204
+ this.children.forEach((com, index) => {
205
+ com.orderNo = index
206
+ })
207
+
208
+ // 5. 标记子节点为 ATTACHED 状态
209
+ child.$phaseShift(LifePhase.ATTACHED, true)
210
+ }
211
+ ```
212
+
213
+ #### 步骤 7: Com 实例化过程
214
+
215
+ 当创建 Com 实例时,会执行以下初始化:
216
+
217
+ ```typescript
218
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/com.ts:264-297
219
+ constructor(options: ComArgs) {
220
+ super(options)
221
+
222
+ // 1. 存储原始数据(向后兼容)
223
+ this[STATE].data = options
224
+
225
+ // 2. 初始化布局
226
+ this[STATE].iRegion = options.regions || this.defaultLayout()
227
+ this.initLayout()
228
+
229
+ // 3. 创建表达式对象
230
+ this[BOUNDED].expression = new Expression({ comKId: this.keyIdentifier })
231
+
232
+ // 4. 生成 UI Props
233
+ this.uiProps = this.generateUiProps()
234
+
235
+ // 5. 内存监控(开发环境)
236
+ if (__watch_memory) {
237
+ incrCmpCount(this.cmpType)
238
+ fRegistry?.register(this, this.cmpType)
239
+ }
240
+
241
+ // 6. 异步创建 Store
242
+ queueMicrotask(() => {
243
+ this.$tryCreateStore()
244
+ })
245
+ }
246
+ ```
247
+
248
+ ## 四、ComFinder 组件查找机制
249
+
250
+ ### 4.1 Com 注册
251
+
252
+ 组件通过 `@registerCom` 装饰器注册:
253
+
254
+ ```typescript
255
+ // packages/neo-ui-common/src/_comTree/kernel/register/register.com.ts:174-191
256
+ function registerCom(com: typeof Com) {
257
+ let { _cmpType, _uiType } = com
258
+ if (!_cmpType && !_uiType) {
259
+ console.warn('register com failed, com must has both static properties: _cmpType and _uiType')
260
+ return
261
+ }
262
+
263
+ // 应用装饰器
264
+ ComDecorator(com)
265
+
266
+ // 建立映射关系
267
+ CmpTypePair.setPair(_cmpType, _uiType)
268
+
269
+ // 注册到全局列表
270
+ COM_DEFS.unshift({
271
+ cmpType: _cmpType,
272
+ uiType: _uiType,
273
+ comClass: com
274
+ })
275
+ }
276
+ ```
277
+
278
+ ### 4.2 Com 查找
279
+
280
+ ```typescript
281
+ // 根据 cmpType 查找对应的 Com 类
282
+ let ComClass = ComFinder.getCom({ cmpType: cmp.cmpType })
283
+ ```
284
+
285
+ ## 五、布局初始化
286
+
287
+ ### 5.1 布局结构
288
+
289
+ Com 可以包含布局信息(regions),布局定义了子组件的排列方式:
290
+
291
+ ```typescript
292
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/com.ts:193-213
293
+ protected initLayout() {
294
+ let regions = this.regions as RegionSchema | undefined
295
+ if (regions) {
296
+ const { template, slots } = regions
297
+ if (!template) {
298
+ console.error('template is required', this)
299
+ return
300
+ }
301
+
302
+ // 根据模板名称查找布局类
303
+ const LayoutClass = XLayout.getLayout(template)
304
+ if (!LayoutClass) {
305
+ throw new Error(`Layout template ${regions?.template} not found`)
306
+ }
307
+
308
+ // 创建布局实例
309
+ const layout = new LayoutClass(template)
310
+ layout.existAsRegions(regions, this)
311
+ if (slots) {
312
+ layout.syncSlots(slots)
313
+ }
314
+
315
+ this[SCOPE].layout = layout
316
+ this[BOUNDED].boundLayout = layout
317
+ }
318
+ }
319
+ ```
320
+
321
+ ### 5.2 布局类型
322
+
323
+ - **SlotLayout**: 插槽布局,支持多个插槽(如 header, body, footer)
324
+ - **FlexLayout**: 弹性布局
325
+ - **GridLayout**: 网格布局
326
+
327
+ ## 六、扩展机制
328
+
329
+ ### 6.1 AgentCom 扩展
330
+
331
+ 在 ComTree 构建完成后,会应用扩展:
332
+
333
+ ```typescript
334
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom/formPageUniCom.ts:237
335
+ this.applyAgentCom()
336
+ ```
337
+
338
+ 扩展可以:
339
+ - 修改组件的属性(uiProps)
340
+ - 扩展组件的方法(通过 AOP)
341
+ - 添加新的子组件
342
+
343
+ ### 6.2 扩展优先级
344
+
345
+ ```typescript
346
+ enum DEV_PRIORITY {
347
+ SYSTEM = 1, // 系统级
348
+ ISV = 2, // ISV 扩展
349
+ CUSTOM = 3 // 自定义扩展
350
+ }
351
+ ```
352
+
353
+ ## 七、变量空间
354
+
355
+ ### 7.1 变量空间初始化
356
+
357
+ 页面级别的变量空间在 `setupVarSpace` 中初始化:
358
+
359
+ ```typescript
360
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom/formPageUniCom.ts:70-103
361
+ setupVarSpace() {
362
+ let masterCom = this.getMasterFormCom()
363
+ let mainProps = masterCom.getProps()
364
+
365
+ // 创建页面变量空间
366
+ const pageVs = new VarSpace({
367
+ key: '$page',
368
+ label: '页面属性',
369
+ observable: false,
370
+ writable: false
371
+ })
372
+
373
+ // 添加页面属性
374
+ pageVs.$appendLeaf('objectApiKey', { ... })
375
+ pageVs.$appendLeaf('recordId', { ... })
376
+ // ...
377
+
378
+ // 绑定到页面
379
+ VarSpaceInTree.bindPageVs(this, pageVs)
380
+ }
381
+ ```
382
+
383
+ ### 7.2 变量作用域
384
+
385
+ - **$page**: 页面级变量
386
+ - **$mainForm**: 主表单变量
387
+ - **$subForm**: 子表单变量
388
+ - **$global**: 全局变量
389
+
390
+ ## 八、渲染准备
391
+
392
+ ### 8.1 ready2render 标志
393
+
394
+ 当 ComTree 构建完成并准备好渲染时,会设置 `ready2render = true`:
395
+
396
+ ```typescript
397
+ // packages/neo-ui-common/src/_comTreeDom/baseCmp/basePage.tsx:55-58
398
+ __com__.on('ready', () => {
399
+ this.onReady2Render(__com__)
400
+ __com__.enableRenderState() // 设置 ready2render = true
401
+ })
402
+ ```
403
+
404
+ ### 8.2 Schema 生成
405
+
406
+ ComTree 构建完成后,通过 `getJsonSchema` 生成 amis Schema:
407
+
408
+ ```typescript
409
+ // packages/neo-ui-common/src/_comTree/standard.coms/com/pageCom.ts:210-227
410
+ getJsonSchema() {
411
+ let topLayoutCom = this.getRootLayoutCom()
412
+ let schema: any = {}
413
+ if (topLayoutCom) {
414
+ schema = topLayoutCom.getJsonSchema()
415
+ } else {
416
+ schema = {
417
+ body: '页面配置错误,没有配置布局',
418
+ type: 'wrapper',
419
+ keyIdentifier: this.keyIdentifier,
420
+ cmpType: 'wrapper',
421
+ __com__: this
422
+ }
423
+ }
424
+ return schema
425
+ }
426
+ ```
427
+
428
+ ## 九、关键数据结构
429
+
430
+ ### 9.1 ComArgs
431
+
432
+ ```typescript
433
+ type ComArgs<T = any> = {
434
+ keyIdentifier: string // 唯一标识
435
+ cmpType: string // 组件类型
436
+ props?: T // 组件属性
437
+ regions?: RegionSchema // 布局信息
438
+ subCmps?: ComArgs[] // 子组件
439
+ orderNo?: number // 排序号
440
+ // ...
441
+ }
442
+ ```
443
+
444
+ ### 9.2 RegionSchema
445
+
446
+ ```typescript
447
+ type RegionSchema = {
448
+ template: string // 布局模板名称
449
+ slots?: { // 插槽定义
450
+ [slotName: string]: SlotArgs
451
+ }
452
+ cells?: object // 单元格配置
453
+ config?: object // 布局配置
454
+ }
455
+ ```
456
+
457
+ ## 十、总结
458
+
459
+ ComTree 的生成是一个递归的过程:
460
+
461
+ 1. **入口**: 页面打开时创建 PageCom
462
+ 2. **数据加载**: Store 加载布局数据
463
+ 3. **树构建**: 通过 `$expandSubTree` 递归创建子节点
464
+ 4. **扩展应用**: 应用 AgentCom 扩展
465
+ 5. **准备渲染**: 设置变量空间,标记 ready2render
466
+ 6. **Schema 生成**: 生成 amis Schema 用于渲染
467
+
468
+ 整个过程是异步的,通过 Promise 和生命周期钩子来协调各个阶段的执行顺序。
469
+
@@ -39,7 +39,9 @@
39
39
  "dependencies": {
40
40
  "neo-register": "^1.1.0",
41
41
  "react": "^16.9.0",
42
- "react-dom": "^16.9.0"
42
+ "react-dom": "^16.9.0",
43
+ "antd": "4.9.4",
44
+ "neo-open-api": "^1.1.11"
43
45
  },
44
46
  "devDependencies": {
45
47
  "@commitlint/cli": "^8.3.5",
@@ -0,0 +1,36 @@
1
+ import * as React from 'react';
2
+
3
+ /**
4
+ * BaseCmpProps 基础组件属性接口
5
+ */
6
+ export interface BaseCmpProps {
7
+ [key: string]: any;
8
+ }
9
+
10
+ /**
11
+ * ScopedComponentType 作用域组件类型接口
12
+ */
13
+ export interface ScopedComponentType {
14
+ [key: string]: any;
15
+ }
16
+
17
+ /**
18
+ * BaseCmp 基础组件类
19
+ * 继承自 React.PureComponent,提供基础组件功能
20
+ */
21
+ export declare class BaseCmp<
22
+ T extends BaseCmpProps = BaseCmpProps,
23
+ S = any
24
+ > extends React.PureComponent<T, S> implements ScopedComponentType {
25
+ props: Readonly<T> & Readonly<{ children?: React.ReactNode }>;
26
+ state: Readonly<S>;
27
+ setState<K extends keyof S>(
28
+ state:
29
+ | ((prevState: Readonly<S>, props: Readonly<T>) => Pick<S, K> | S | null)
30
+ | (Pick<S, K> | S | null),
31
+ callback?: () => void
32
+ ): void;
33
+ forceUpdate(callback?: () => void): void;
34
+ render(): React.ReactNode;
35
+ }
36
+
@@ -2,7 +2,12 @@ import * as React from 'react';
2
2
  import { Card, Row, Col, Spin, Empty, Avatar, Button } from 'antd';
3
3
  import { UserOutlined, PhoneOutlined, ReloadOutlined } from '@ant-design/icons';
4
4
  // @ts-ignore
5
- import { xObject } from 'neo-open-api'; // Neo Open API
5
+ import { xObject } from 'neo-open-api';
6
+
7
+ // Neo Open API// 引入 neo-ui-common / BaseCmp
8
+ // @ts-ignore
9
+ import { BaseCmp } from 'neo-ui-common';
10
+
6
11
  import './style.scss';
7
12
 
8
13
  interface EntityCardListProps {
@@ -26,7 +31,7 @@ interface EntityCardListState {
26
31
  error: string | null;
27
32
  }
28
33
 
29
- export default class EntityCardList extends React.PureComponent<
34
+ export default class EntityCardList extends BaseCmp<
30
35
  EntityCardListProps,
31
36
  EntityCardListState
32
37
  > {
@@ -47,7 +52,7 @@ export default class EntityCardList extends React.PureComponent<
47
52
  this.loadObjectData();
48
53
  }
49
54
 
50
- componentDidUpdate(prevProps: EntityCardListProps) {
55
+ componentDidUpdate(prevProps: Readonly<EntityCardListProps>) {
51
56
  const { xObjectDataApi } = this.props;
52
57
  if (
53
58
  xObjectDataApi?.xObjectApiKey !==
@@ -58,10 +63,13 @@ export default class EntityCardList extends React.PureComponent<
58
63
  }
59
64
  }
60
65
 
61
- async loadObjectData() {
66
+ async loadObjectData(parma1?: any) {
62
67
  const { xObjectDataApi } = this.props;
63
68
  const { autoFetchData } = xObjectDataApi || {};
64
69
 
70
+ // 测试输出,输出当前参数
71
+ console.log('parma1:', parma1);
72
+
65
73
  if (autoFetchData) {
66
74
  // 方式一:直接从 props 中取实体数据源相关数据
67
75
  const { entityData: entityDataList } = this.props;
@@ -189,7 +197,7 @@ export default class EntityCardList extends React.PureComponent<
189
197
  />
190
198
  ) : (
191
199
  <Row gutter={[16, 16]}>
192
- {objectDataList.map((object, index) =>
200
+ {objectDataList.map((object: ContactData, index: number) =>
193
201
  this.renderEntityCard(object, index),
194
202
  )}
195
203
  </Row>
@@ -50,7 +50,6 @@ export class EntityCardListModel {
50
50
  apiKey: 'loadObjectData',
51
51
  label: '重新获取数据列表',
52
52
  helpTextKey: '获取实体业务数据列表',
53
- funcInParams: [],
54
53
  },
55
54
  ];
56
55
 
@@ -27,9 +27,9 @@ import {
27
27
  import { xObject } from 'neo-open-api'; // Neo Open API
28
28
  // @ts-ignore
29
29
  import isEqual from 'lodash/isEqual';
30
- // 引入 neo-ui-common / aop
30
+ // 引入 neo-ui-common / NeoEvent
31
31
  // @ts-ignore
32
- import { aop } from 'neo-ui-common'; // 后续考虑 使用 props.dispatchEvent 方法替代
32
+ import { NeoEvent } from 'neo-ui-common'; // 后续考虑 使用 props.dispatchEvent 方法替代
33
33
  import './style.scss';
34
34
 
35
35
  const { Option } = Select;
@@ -233,7 +233,7 @@ export default class EntityForm extends React.PureComponent<
233
233
  /**
234
234
  * 表单提交事件
235
235
  */
236
- @aop
236
+ @NeoEvent.dispatch
237
237
  onSubmit() {
238
238
  console.log('触发了表单提交事件:', this.props);
239
239
  }
@@ -58,10 +58,9 @@ export class EntityFormModel {
58
58
  events = [
59
59
  {
60
60
  apiKey: 'onSubmit', // 事件名称
61
- // description: '这是一个表单提交事件', // 暂未使用
62
61
  label: '提交表单后', // 事件
63
- helpText: '表单提交后触发该事件' // 信息icon hover 时的提示文本
64
- }
62
+ helpText: '表单提交后触发该事件', // 信息icon hover 时的提示文本
63
+ },
65
64
  ];
66
65
 
67
66
  /**
@@ -33,6 +33,11 @@ import moment from 'moment';
33
33
  import { xObject } from 'neo-open-api'; // Neo Open API
34
34
  // @ts-ignore
35
35
  import isEqual from 'lodash/isEqual';
36
+
37
+ // Neo Open API// 引入 neo-ui-common / BaseCmp
38
+ // @ts-ignore
39
+ import { BaseCmp } from 'neo-ui-common';
40
+
36
41
  import './style.scss';
37
42
 
38
43
  const { Option } = Select;
@@ -120,7 +125,7 @@ interface EntityTableState {
120
125
  * XObject 数据表格组件
121
126
  * 支持对 Neo 平台的 XObject 实体对象进行增删改查操作
122
127
  */
123
- export default class EntityTable extends React.PureComponent<
128
+ export default class EntityTable extends BaseCmp<
124
129
  EntityTableProps,
125
130
  EntityTableState
126
131
  > {
@@ -50,6 +50,28 @@ export class EntityTableModel {
50
50
  },
51
51
  };
52
52
 
53
+ // 当前组件支持的函数列表(其他组件可触发当前组件的函数)
54
+ functions = [
55
+ {
56
+ apiKey: 'loadData',
57
+ label: '刷新表格',
58
+ helpTextKey: '刷新当前表格数据',
59
+ },
60
+ {
61
+ apiKey: 'handleDelete',
62
+ label: '删除记录',
63
+ helpTextKey: '删除表格中指定记录',
64
+ funcInParams: [
65
+ {
66
+ apiKey: 'id',
67
+ label: '记录ID',
68
+ type: 'String',
69
+ required: true,
70
+ },
71
+ ],
72
+ },
73
+ ];
74
+
53
75
  /**
54
76
  * 组件属性配置模式
55
77
  * 支持静态配置:propsSchema,优先级比 propsSchemaCreator 低
@@ -1,7 +1,7 @@
1
1
  const { execSync } = require('child_process');
2
2
 
3
3
  // 所有需要废弃的版本
4
- const versionsToDeprecate = ["1.9.0", "1.9.1", "1.9.2", "1.9.3"];
4
+ const versionsToDeprecate = ["1.9.5", "1.9.6", "1.9.7", "1.9.8"];
5
5
 
6
6
  const packageName = 'neo-cmp-cli';
7
7
  const deprecateMessage = '此版本为开发中版本(存在 bug),请升级到最新版本。';