@nocobase/client-v2 2.1.1 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/es/index.mjs
CHANGED
|
@@ -1240,7 +1240,7 @@ ctx.render(<JsItem />);
|
|
|
1240
1240
|
border-top-color: transparent;
|
|
1241
1241
|
background-color: transparent;
|
|
1242
1242
|
}
|
|
1243
|
-
`,children:"x"})})})]})};class vZ{render(e,t){if(!e)return null;try{return(0,s.jsx)(vK,{value:e,...t})}catch(e){return console.error("渲染失败:",e),(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 渲染错误:",e.message]})}}edit(e){try{return(0,s.jsx)(vQ,{...e})}catch(e){return(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 编辑器加载错误:",e.message]})}}}class v0 extends __rspack_external_liquidjs.Liquid{transformLiquidContext(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t={};for(let l of e){let e=l.replace(/^ctx\./,"").split("."),o=t;for(let t=0;t<e.length;t++){let n=e[t];t===e.length-1?o[n]=`{{${l}}}`:(o[n]=o[n]||{},o=o[n])}}return t}async render(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};try{return await this.parseAndRender(e,t)}catch(e){return console.error("[Liquid] 模板解析失败:",e),`<pre style="color:red;">Liquid 模板错误:${e.message}</pre>`}}isFieldUsed(e,t){return t.some(t=>t.replace(/^ctx\./,"").endsWith(e))}enrichArrayFieldsSelective(e,t){if(e&&"object"==typeof e)for(let l in e){let o=e[l];if(Array.isArray(o)&&o.length&&"object"==typeof o[0]){let e=o;Object.keys(e[0]).filter(o=>["string","number","boolean"].includes(typeof e[0][o])&&this.isFieldUsed(`${l}.${o}`,t)).forEach(t=>{e[t]=e.map(e=>null!=e[t]?e[t]:"").join(",")}),e.forEach(e=>this.enrichArrayFieldsSelective(e,t))}else o&&"object"==typeof o&&this.enrichArrayFieldsSelective(o,t)}}async renderWithFullContext(e,t){if(e)try{"number"==typeof e&&(e=String(e)),e=e.replace(/\{\{\s*t\s*\(\s*(['"])([\s\S]*?)\1\s*(?:,\s*\{\s*ns\s*:\s*(['"])([\s\S]*?)\3\s*\}\s*)?\)\s*\}\}/g,(e,l,o,n,i)=>{try{let e=i?t.t(o,{ns:i}):t.t(o);if(null==e)return"";return/[{][{%]/.test(e)?`{% raw %}${e}{% endraw %}`:e}catch{return e}});let l=await this.fullVariables(e),o=l.map(e=>this.transformLiquidContext([e])),n=(await Promise.all(o.map(e=>t.resolveJsonTemplate(e)))).reduce((e,t)=>(0,c.merge)(e,t),{});return this.enrichArrayFieldsSelective(n,l),await this.render(e,{ctx:n})}catch(t){return e}}constructor(e){super({extname:".liquid",cache:!0,...e}),this.registerFilter("t",e.ctx.t),this.registerFilter("log",e=>(console.log("[Liquid log]",e),e))}}let v1=()=>{let e=(0,u.useFlowEngine)({throwError:!1});if(!e)return{isMobileLayout:!1,setIsMobileLayout:()=>{}};let t=e.getModel(eX);return t?{isMobileLayout:t.isMobileLayout,setIsMobileLayout:t.setIsMobileLayout.bind(t)}:{isMobileLayout:!1,setIsMobileLayout:()=>{}}};function v2(e){let{flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n}=e;return o$({flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n,getLayoutModel:e=>oq(e,{required:!0})})}var v5=__webpack_require__(9652),v8=__webpack_require__(6681),v4=__webpack_require__(9784),v3=__webpack_require__(65);class v6 extends iz{async load(){this.app.addComponents({FlowRoute:oX}),this.app.flowEngine.setModelRepository(new vw(this.app));let e=Object.fromEntries(Object.entries(l).filter(e=>{let[,t]=e;return"function"==typeof t&&t.prototype instanceof u.FlowModel}));this.flowEngine.registerModels(e),this.flowEngine.registerActions(o),this.flowEngine.registerActions(t),this.flowEngine.flowSettings.registerComponents({IconPicker:ed.ar,DefaultValue:vx,FlowSettingsVariableTextArea:iU.n}),this.flowEngine.flowSettings.addToolbarItem({key:"dynamic-flows-editor",component:vA,visible:e=>e.getEvents().size>0,sort:0});let n=new vZ;this.flowEngine.context.defineProperty("markdown",{get:()=>n});let i=new v0({ctx:this.flowEngine.context});this.flowEngine.context.defineProperty("liquid",{get:()=>i}),this.flowEngine.context.defineMethod("previewRunJS",async function(e,t){let l=await Promise.resolve().then(__webpack_require__.bind(__webpack_require__,426));return await l.previewRunJS(String(e??""),this,{version:t})},{description:"Preview/diagnose a RunJS snippet (lint + sandbox execution).",detail:"(code: string, version?: string) => Promise<{ success: boolean; message: string }>",params:[{name:"code",type:"string",description:"RunJS code to preview."},{name:"version",type:"string",description:"RunJS version override (e.g. v1/v2)."}],returns:{type:"Promise<PreviewRunJSResult>",description:"Preview result."},completion:{insertText:"await ctx.previewRunJS('console.log(1)', 'v2')"}})}}let v9={"ar-EG":"ar","az-AZ":"az","bg-BG":"bg","bn-BD":"bn-bd","by-BY":"en","ca-ES":"ca","cs-CZ":"cs","da-DK":"da","de-DE":"de","el-GR":"el","en-GB":"en-gb","en-US":"en","es-ES":"es","et-EE":"et","fa-IR":"fa","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-FR":"fr","ga-IE":"ga","gl-ES":"gl","he-IL":"he","hi-IN":"hi","hr-HR":"hr","hu-HU":"hu","hy-AM":"hy-am","id-ID":"id","is-IS":"is","it-IT":"it","ja-JP":"ja","ka-GE":"ka","kk-KZ":"kk","km-KH":"km","kn-IN":"kn","ko-KR":"ko","ku-IQ":"ku","lt-LT":"lt","lv-LV":"lv","mk-MK":"mk","ml-IN":"ml","mn-MN":"mn","ms-MY":"ms","nb-NO":"nb","ne-NP":"ne","nl-BE":"nl-be","nl-NL":"nl","pl-PL":"pl","pt-BR":"pt-br","pt-PT":"pt","ro-RO":"ro","ru-RU":"ru","si-LK":"si","sk-SK":"sk","sl-SI":"sl","sr-RS":"sr","sv-SE":"sv","ta-IN":"ta","th-TH":"th","tk-TK":"tk","tr-TR":"tr","uk-UA":"uk","ur-PK":"ur","vi-VN":"vi","zh-CN":"zh-cn","zh-HK":"zh-hk","zh-TW":"zh-tw"};class v7{atX0SecondsPastTheMinuteGt20(){return this.data.atX0SecondsPastTheMinuteGt20}atX0MinutesPastTheHourGt20(){return this.data.atX0MinutesPastTheHourGt20}commaMonthX0ThroughMonthX1(){return this.data.commaMonthX0ThroughMonthX1}commaYearX0ThroughYearX1(){return this.data.commaYearX0ThroughYearX1}use24HourTimeFormatByDefault(){return this.data.use24HourTimeFormatByDefault}anErrorOccuredWhenGeneratingTheExpressionD(){return this.data.anErrorOccuredWhenGeneratingTheExpressionD}everyMinute(){return this.data.everyMinute}everyHour(){return this.data.everyHour}atSpace(){return this.data.atSpace}everyMinuteBetweenX0AndX1(){return this.data.everyMinuteBetweenX0AndX1}at(){return this.data.at}spaceAnd(){return this.data.spaceAnd}everySecond(){return this.data.everySecond}everyX0Seconds(){return this.data.everyX0Seconds}secondsX0ThroughX1PastTheMinute(){return this.data.secondsX0ThroughX1PastTheMinute}atX0SecondsPastTheMinute(){return this.data.atX0SecondsPastTheMinute}everyX0Minutes(){return this.data.everyX0Minutes}minutesX0ThroughX1PastTheHour(){return this.data.minutesX0ThroughX1PastTheHour}atX0MinutesPastTheHour(){return this.data.atX0MinutesPastTheHour}everyX0Hours(){return this.data.everyX0Hours}betweenX0AndX1(){return this.data.betweenX0AndX1}atX0(){return this.data.atX0}commaEveryDay(){return this.data.commaEveryDay}commaEveryX0DaysOfTheWeek(){return this.data.commaEveryX0DaysOfTheWeek}commaX0ThroughX1(){return this.data.commaX0ThroughX1}commaAndX0ThroughX1(){return this.data.commaAndX0ThroughX1}first(){return this.data.first}second(){return this.data.second}third(){return this.data.third}fourth(){return this.data.fourth}fifth(){return this.data.fifth}commaOnThe(){return this.data.commaOnThe}spaceX0OfTheMonth(){return this.data.spaceX0OfTheMonth}lastDay(){return this.data.lastDay}commaOnTheLastX0OfTheMonth(){return this.data.commaOnTheLastX0OfTheMonth}commaOnlyOnX0(){return this.data.commaOnlyOnX0}commaAndOnX0(){return this.data.commaAndOnX0}commaEveryX0Months(){return this.data.commaEveryX0Months}commaOnlyInX0(){return this.data.commaOnlyInX0}commaOnTheLastDayOfTheMonth(){return this.data.commaOnTheLastDayOfTheMonth}commaOnTheLastWeekdayOfTheMonth(){return this.data.commaOnTheLastWeekdayOfTheMonth}commaDaysBeforeTheLastDayOfTheMonth(){return this.data.commaDaysBeforeTheLastDayOfTheMonth}firstWeekday(){return this.data.firstWeekday}weekdayNearestDayX0(){return this.data.weekdayNearestDayX0}commaOnTheX0OfTheMonth(){return this.data.commaOnTheX0OfTheMonth}commaEveryX0Days(){return this.data.commaEveryX0Days}commaBetweenDayX0AndX1OfTheMonth(){return this.data.commaBetweenDayX0AndX1OfTheMonth}commaOnDayX0OfTheMonth(){return this.data.commaOnDayX0OfTheMonth}commaEveryHour(){return this.data.commaEveryHour}commaEveryX0Years(){return this.data.commaEveryX0Years}commaStartingX0(){return this.data.commaStartingX0}daysOfTheWeek(){return this.data.daysOfTheWeek}monthsOfTheYear(){return this.data.monthsOfTheYear}constructor(e){this.data=e}}let _e=e=>{(__rspack_external_cronstrue.default.default?__rspack_external_cronstrue.default.default:__rspack_external_cronstrue.default).initialize({load(t){t[null==e?void 0:e.lang]=new v7(null==e?void 0:e.cronstrue)}})};class _t extends iz{async afterAdd(){let e=this.app.apiClient,t=e.auth.locale;try{var l;let o=await e.request({url:"app:getLang",params:{locale:t},headers:{"X-Role":"anonymous"}}),n=(null==o||null==(l=o.data)?void 0:l.data)||{};this.engine.context.defineProperty("locales",{value:n}),this.app.use(g.App,{component:!1}),n.lang&&(e.auth.setLocale(n.lang),this.app.setDocumentLanguage(n.lang),this.app.i18n.changeLanguage(n.lang)),Object.keys(n.resources||{}).forEach(e=>{this.app.i18n.addResources(n.lang,e,n.resources[e]||{})}),(0,__rspack_external__formily_validator_5f6f1884.setValidateLanguage)(n.lang),_e(n);let i=v9[n.lang]||"en";await __webpack_require__(8817)(`./${i}`),m6.default.locale(i),window.cronLocale=n.cron}catch(e){throw e}}}let _l=["/signin","/signup","/forgot-password","/reset-password"];function _o(e,t){if(!t)return e;let l=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=RegExp(`^${l.replace(/\/?$/,"")}(\\/|$)`);return e.replace(o,"/")||e}function _n(e,t){let l=_o(e,t);return _l.some(e=>l===e||l.startsWith(`${e}/`))}function _i(e,t){let l=_o(e,t);return"/admin"===l||l.startsWith("/admin/")}function _r(e,t){return(e.router.matchRoutes(t)||[]).some(e=>{var t;return(null==e||null==(t=e.route)?void 0:t.authCheck)===!0})}function _a(e,t){return _i(t,e.router.getBasename())||_r(e,t)}function _s(e,t){return _n(t,e.router.getBasename())||e.router.isSkippedAuthCheckRoute(t)?"skipped":_a(e,t)?"required":"unchecked"}let _d=(0,p.createContext)(null);function _u(){return(0,p.useContext)(_d)}function _c(){var e,t;let{allowAnonymous:l}=(0,lg.v6)(),o=(0,u.useFlowEngine)(),n=null==o||null==(t=o.context)||null==(e=t.user)?void 0:e.roles;return(0,p.useMemo)(()=>{let e=e=>{var t;return null==e?"":(null==o||null==(t=o.context)?void 0:t.t)?o.context.t(e):e},t=(n||[]).filter(e=>(null==e?void 0:e.name)!=="__union__").map(t=>({name:t.name,title:e(t.title)}));return l&&t.push({name:"anonymous",title:"Anonymous"}),t},[l,o,n])}_d.displayName="CurrentUserContext";let _p=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),[n,i]=(0,p.useState)(!0),[r,a]=(0,p.useState)(null),d=(0,p.useRef)(!1);if((0,p.useEffect)(()=>{let e=!0,t=l.router.getBasename(),n=_n(o.pathname,t)||l.router.isSkippedAuthCheckRoute(o.pathname),r=_a(l,o.pathname);if(n||!r){i(!1),a(null);return}return d.current||i(!0),a(null),(async()=>{try{await l.dataSourceManager.ensureLoaded(),d.current=!0,e&&i(!1)}catch(t){if(!e)return;i(!1),a(t instanceof Error?t:Error(String(t)))}})(),()=>{e=!1}},[l,o.pathname]),r)throw r;return n?l.renderComponent("AppSpin"):(0,s.jsx)(s.Fragment,{children:t})},_m=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),n=(0,h.useNavigate)(),[i,r]=(0,p.useState)({loading:!0}),a=(0,p.useRef)(o);a.current=o;let d=_s(l,o.pathname);return((0,p.useEffect)(()=>{let e=!0;return"required"!==d?void r({loading:!1}):(r(e=>e.loading?e:{...e,loading:!0}),(async()=>{var t,o;try{let o=await l.apiClient.request({url:"/auth:check",skipNotify:!0,skipAuth:!0});if(!e)return;let i=null==o||null==(t=o.data)?void 0:t.data;if((null==i?void 0:i.code)===302)return void r({loading:!1});if((null==i?void 0:i.id)==null)return void n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});let s=(0,u.createCollectionContextMeta)(()=>{var e,t;return(null==(t=l.flowEngine.context.dataSourceManager)||null==(e=t.getDataSource("main"))?void 0:e.getCollection("users"))||null},l.flowEngine.translate("Current user"));s.sort=1e3,l.flowEngine.context.defineProperty("user",{value:i,resolveOnServer:!0,meta:s}),r({data:null==o?void 0:o.data,loading:!1})}catch(t){if(!e)return;if((null==t||null==(o=t.response)?void 0:o.status)===401||(null==t?void 0:t.status)===401)return void n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});throw r({loading:!1}),t}})(),()=>{e=!1})},[l,d,n]),i.loading)?l.renderComponent("AppSpin"):(0,s.jsx)(_d.Provider,{value:i,children:t})},_h=()=>{var e,t;let l=(0,f.n)(),o=!!(null==l||null==(t=l.apiClient)||null==(e=t.auth)?void 0:e.token),n=eP(l);return o?(0,s.jsx)(h.Navigate,{replace:!0,to:"/admin"}):(0,s.jsx)(h.Navigate,{replace:!0,to:`/signin?redirect=${encodeURIComponent(n)}`})};class _f extends iz{async afterAdd(){await this.addPlugins()}async load(){this.addComponents(),this.addRoutes(),this.app.use(_p),this.app.use(_m),this.app.flowEngine.registerModels({AdminLayoutModel:oV,AdminLayoutMenuItemModel:t9,AdminSettingsLayoutModel:v8.C}),this.app.layoutManager.registerLayout({routeName:"admin",routePath:"/admin",uid:eX,layoutModelClass:"AdminLayoutModel"}),this.app.pluginSettingsManager.addMenuItem({key:"plugin-manager",title:this.app.i18n.t("Plugin manager"),icon:"ApiOutlined",aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"plugin-manager",key:"index",title:this.app.i18n.t("Plugin manager"),componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,9784)),aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addMenuItem({key:"system-settings",title:this.app.i18n.t("System settings"),icon:"SettingOutlined",aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"system-settings",key:"index",title:this.app.i18n.t("System settings"),componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,65)),aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addMenuItem({key:"security",title:this.app.i18n.t("Security"),icon:"SafetyOutlined",aclSnippet:"pm.security"})}addRoutes(){this.router.add("root",{path:"/",element:(0,s.jsx)(_h,{})}),this.router.add("not-found",{path:"*",Component:I.bM}),this.router.add("admin.settings",{path:"/admin/settings",componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,9652))}),this.router.add("admin.settings.route-empty",{path:"*",Component:h.Outlet})}addComponents(){}async addPlugins(){await this.app.pm.add(v6),await this.app.pm.add(_t,{name:"builtin-locale"})}}var _g=__webpack_require__(5026);let _y={type:"boolean","x-content":'{{t("Unique")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},_v={type:"boolean","x-content":'{{t("Primary")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},__={type:"boolean",title:'{{t("Auto increment")}}',"x-content":'{{t("Auto increment")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly }}"},_b={type:"boolean",title:'{{t("Default value")}}',"x-content":'{{t("Automatically generate default values")}}',"x-decorator":"FormItem","x-component":"Checkbox",default:!0},_x={type:"string",title:'{{t("Relationship type")}}',required:!0,"x-disabled":!0,"x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('HasOne')}}",value:"hasOne"},{label:"{{t('HasMany')}}",value:"hasMany"},{label:"{{t('BelongsTo')}}",value:"belongsTo"},{label:"{{t('BelongsToMany')}}",value:"belongsToMany"}]},_M={onDelete:{type:"string",title:'{{t("ON DELETE")}}',required:!0,default:"SET NULL","x-disabled":"{{ !createOnly }}","x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('SET NULL')}}",value:"SET NULL"},{label:"{{t('RESTRICT')}}",value:"RESTRICT"},{label:"{{t('CASCADE')}}",value:"CASCADE"},{label:"{{t('NO ACTION')}}",value:"NO ACTION"}]}},_w={reverse:{type:"void","x-component":"div",properties:{autoCreateReverseField:{type:"boolean",default:!1,"x-decorator":"FormItem","x-component":"Checkbox","x-content":'{{t("Create inverse field in the target collection")}}'},"reverseField.type":{..._x,title:'{{t("Inverse relationship type")}}'},"reverseField.uiSchema.title":{type:"string",title:'{{t("Inverse field display name")}}',default:"{{record.title}}",required:!0,"x-decorator":"FormItem","x-component":"Input","x-disabled":"{{ !showReverseFieldConfig }}"},"reverseField.name":{type:"string",title:'{{t("Inverse field name")}}',required:!0,"x-decorator":"FormItem","x-component":"Input","x-validator":"uid","x-disabled":"{{ !showReverseFieldConfig }}",description:"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}"}}}},_S={"uiSchema.x-component-props.picker":{type:"string",title:'{{t("Picker")}}',"x-decorator":"FormItem","x-component":"Radio.Group",default:"date",enum:[{label:'{{t("Date")}}',value:"date"},{label:'{{t("Month")}}',value:"month"},{label:'{{t("Quarter")}}',value:"quarter"},{label:'{{t("Year")}}',value:"year"}]},"uiSchema.x-component-props.dateFormat":{type:"string",title:'{{t("Date format")}}',"x-decorator":"FormItem","x-component":"ExpiresRadio","x-decorator-props":{},"x-component-props":{className:(0,S.css)`
|
|
1243
|
+
`,children:"x"})})})]})};class vZ{render(e,t){if(!e)return null;try{return(0,s.jsx)(vK,{value:e,...t})}catch(e){return console.error("渲染失败:",e),(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 渲染错误:",e.message]})}}edit(e){try{return(0,s.jsx)(vQ,{...e})}catch(e){return(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 编辑器加载错误:",e.message]})}}}class v0 extends __rspack_external_liquidjs.Liquid{transformLiquidContext(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t={};for(let l of e){let e=l.replace(/^ctx\./,"").split("."),o=t;for(let t=0;t<e.length;t++){let n=e[t];t===e.length-1?o[n]=`{{${l}}}`:(o[n]=o[n]||{},o=o[n])}}return t}async render(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};try{return await this.parseAndRender(e,t)}catch(e){return console.error("[Liquid] 模板解析失败:",e),`<pre style="color:red;">Liquid 模板错误:${e.message}</pre>`}}isFieldUsed(e,t){return t.some(t=>t.replace(/^ctx\./,"").endsWith(e))}enrichArrayFieldsSelective(e,t){if(e&&"object"==typeof e)for(let l in e){let o=e[l];if(Array.isArray(o)&&o.length&&"object"==typeof o[0]){let e=o;Object.keys(e[0]).filter(o=>["string","number","boolean"].includes(typeof e[0][o])&&this.isFieldUsed(`${l}.${o}`,t)).forEach(t=>{e[t]=e.map(e=>null!=e[t]?e[t]:"").join(",")}),e.forEach(e=>this.enrichArrayFieldsSelective(e,t))}else o&&"object"==typeof o&&this.enrichArrayFieldsSelective(o,t)}}async renderWithFullContext(e,t){if(e)try{"number"==typeof e&&(e=String(e)),e=e.replace(/\{\{\s*t\s*\(\s*(['"])([\s\S]*?)\1\s*(?:,\s*\{\s*ns\s*:\s*(['"])([\s\S]*?)\3\s*\}\s*)?\)\s*\}\}/g,(e,l,o,n,i)=>{try{let e=i?t.t(o,{ns:i}):t.t(o);if(null==e)return"";return/[{][{%]/.test(e)?`{% raw %}${e}{% endraw %}`:e}catch{return e}});let l=await this.fullVariables(e),o=l.map(e=>this.transformLiquidContext([e])),n=(await Promise.all(o.map(e=>t.resolveJsonTemplate(e)))).reduce((e,t)=>(0,c.merge)(e,t),{});return this.enrichArrayFieldsSelective(n,l),await this.render(e,{ctx:n})}catch(t){return e}}constructor(e){super({extname:".liquid",cache:!0,...e}),this.registerFilter("t",e.ctx.t),this.registerFilter("log",e=>(console.log("[Liquid log]",e),e))}}let v1=()=>{let e=(0,u.useFlowEngine)({throwError:!1});if(!e)return{isMobileLayout:!1,setIsMobileLayout:()=>{}};let t=e.getModel(eX);return t?{isMobileLayout:t.isMobileLayout,setIsMobileLayout:t.setIsMobileLayout.bind(t)}:{isMobileLayout:!1,setIsMobileLayout:()=>{}}};function v2(e){let{flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n}=e;return o$({flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n,getLayoutModel:e=>oq(e,{required:!0})})}var v5=__webpack_require__(9652),v8=__webpack_require__(6681),v4=__webpack_require__(9784),v3=__webpack_require__(65);class v6 extends iz{async load(){this.app.addComponents({FlowRoute:oX}),this.app.flowEngine.setModelRepository(new vw(this.app));let e=Object.fromEntries(Object.entries(l).filter(e=>{let[,t]=e;return"function"==typeof t&&t.prototype instanceof u.FlowModel}));this.flowEngine.registerModels(e),this.flowEngine.registerActions(o),this.flowEngine.registerActions(t),this.flowEngine.flowSettings.registerComponents({IconPicker:ed.ar,DefaultValue:vx,FlowSettingsVariableTextArea:iU.n}),this.flowEngine.flowSettings.addToolbarItem({key:"dynamic-flows-editor",component:vA,visible:e=>e.getEvents().size>0,sort:0});let n=new vZ;this.flowEngine.context.defineProperty("markdown",{get:()=>n});let i=new v0({ctx:this.flowEngine.context});this.flowEngine.context.defineProperty("liquid",{get:()=>i}),this.flowEngine.context.defineMethod("previewRunJS",async function(e,t){let l=await Promise.resolve().then(__webpack_require__.bind(__webpack_require__,426));return await l.previewRunJS(String(e??""),this,{version:t})},{description:"Preview/diagnose a RunJS snippet (lint + sandbox execution).",detail:"(code: string, version?: string) => Promise<{ success: boolean; message: string }>",params:[{name:"code",type:"string",description:"RunJS code to preview."},{name:"version",type:"string",description:"RunJS version override (e.g. v1/v2)."}],returns:{type:"Promise<PreviewRunJSResult>",description:"Preview result."},completion:{insertText:"await ctx.previewRunJS('console.log(1)', 'v2')"}})}}let v9={"ar-EG":"ar","az-AZ":"az","bg-BG":"bg","bn-BD":"bn-bd","by-BY":"en","ca-ES":"ca","cs-CZ":"cs","da-DK":"da","de-DE":"de","el-GR":"el","en-GB":"en-gb","en-US":"en","es-ES":"es","et-EE":"et","fa-IR":"fa","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-FR":"fr","ga-IE":"ga","gl-ES":"gl","he-IL":"he","hi-IN":"hi","hr-HR":"hr","hu-HU":"hu","hy-AM":"hy-am","id-ID":"id","is-IS":"is","it-IT":"it","ja-JP":"ja","ka-GE":"ka","kk-KZ":"kk","km-KH":"km","kn-IN":"kn","ko-KR":"ko","ku-IQ":"ku","lt-LT":"lt","lv-LV":"lv","mk-MK":"mk","ml-IN":"ml","mn-MN":"mn","ms-MY":"ms","nb-NO":"nb","ne-NP":"ne","nl-BE":"nl-be","nl-NL":"nl","pl-PL":"pl","pt-BR":"pt-br","pt-PT":"pt","ro-RO":"ro","ru-RU":"ru","si-LK":"si","sk-SK":"sk","sl-SI":"sl","sr-RS":"sr","sv-SE":"sv","ta-IN":"ta","th-TH":"th","tk-TK":"tk","tr-TR":"tr","uk-UA":"uk","ur-PK":"ur","vi-VN":"vi","zh-CN":"zh-cn","zh-HK":"zh-hk","zh-TW":"zh-tw"};class v7{atX0SecondsPastTheMinuteGt20(){return this.data.atX0SecondsPastTheMinuteGt20}atX0MinutesPastTheHourGt20(){return this.data.atX0MinutesPastTheHourGt20}commaMonthX0ThroughMonthX1(){return this.data.commaMonthX0ThroughMonthX1}commaYearX0ThroughYearX1(){return this.data.commaYearX0ThroughYearX1}use24HourTimeFormatByDefault(){return this.data.use24HourTimeFormatByDefault}anErrorOccuredWhenGeneratingTheExpressionD(){return this.data.anErrorOccuredWhenGeneratingTheExpressionD}everyMinute(){return this.data.everyMinute}everyHour(){return this.data.everyHour}atSpace(){return this.data.atSpace}everyMinuteBetweenX0AndX1(){return this.data.everyMinuteBetweenX0AndX1}at(){return this.data.at}spaceAnd(){return this.data.spaceAnd}everySecond(){return this.data.everySecond}everyX0Seconds(){return this.data.everyX0Seconds}secondsX0ThroughX1PastTheMinute(){return this.data.secondsX0ThroughX1PastTheMinute}atX0SecondsPastTheMinute(){return this.data.atX0SecondsPastTheMinute}everyX0Minutes(){return this.data.everyX0Minutes}minutesX0ThroughX1PastTheHour(){return this.data.minutesX0ThroughX1PastTheHour}atX0MinutesPastTheHour(){return this.data.atX0MinutesPastTheHour}everyX0Hours(){return this.data.everyX0Hours}betweenX0AndX1(){return this.data.betweenX0AndX1}atX0(){return this.data.atX0}commaEveryDay(){return this.data.commaEveryDay}commaEveryX0DaysOfTheWeek(){return this.data.commaEveryX0DaysOfTheWeek}commaX0ThroughX1(){return this.data.commaX0ThroughX1}commaAndX0ThroughX1(){return this.data.commaAndX0ThroughX1}first(){return this.data.first}second(){return this.data.second}third(){return this.data.third}fourth(){return this.data.fourth}fifth(){return this.data.fifth}commaOnThe(){return this.data.commaOnThe}spaceX0OfTheMonth(){return this.data.spaceX0OfTheMonth}lastDay(){return this.data.lastDay}commaOnTheLastX0OfTheMonth(){return this.data.commaOnTheLastX0OfTheMonth}commaOnlyOnX0(){return this.data.commaOnlyOnX0}commaAndOnX0(){return this.data.commaAndOnX0}commaEveryX0Months(){return this.data.commaEveryX0Months}commaOnlyInX0(){return this.data.commaOnlyInX0}commaOnTheLastDayOfTheMonth(){return this.data.commaOnTheLastDayOfTheMonth}commaOnTheLastWeekdayOfTheMonth(){return this.data.commaOnTheLastWeekdayOfTheMonth}commaDaysBeforeTheLastDayOfTheMonth(){return this.data.commaDaysBeforeTheLastDayOfTheMonth}firstWeekday(){return this.data.firstWeekday}weekdayNearestDayX0(){return this.data.weekdayNearestDayX0}commaOnTheX0OfTheMonth(){return this.data.commaOnTheX0OfTheMonth}commaEveryX0Days(){return this.data.commaEveryX0Days}commaBetweenDayX0AndX1OfTheMonth(){return this.data.commaBetweenDayX0AndX1OfTheMonth}commaOnDayX0OfTheMonth(){return this.data.commaOnDayX0OfTheMonth}commaEveryHour(){return this.data.commaEveryHour}commaEveryX0Years(){return this.data.commaEveryX0Years}commaStartingX0(){return this.data.commaStartingX0}daysOfTheWeek(){return this.data.daysOfTheWeek}monthsOfTheYear(){return this.data.monthsOfTheYear}constructor(e){this.data=e}}let _e=e=>{(__rspack_external_cronstrue.default.default?__rspack_external_cronstrue.default.default:__rspack_external_cronstrue.default).initialize({load(t){t[null==e?void 0:e.lang]=new v7(null==e?void 0:e.cronstrue)}})};class _t extends iz{async afterAdd(){let e=this.app.apiClient,t=e.auth.locale;try{var l;let o=await e.request({url:"app:getLang",params:{locale:t},headers:{"X-Role":"anonymous"}}),n=(null==o||null==(l=o.data)?void 0:l.data)||{};this.engine.context.defineProperty("locales",{value:n}),this.app.use(g.App,{component:!1}),n.lang&&(e.auth.setLocale(n.lang),this.app.setDocumentLanguage(n.lang),this.app.i18n.changeLanguage(n.lang)),Object.keys(n.resources||{}).forEach(e=>{this.app.i18n.addResources(n.lang,e,n.resources[e]||{})}),(0,__rspack_external__formily_validator_5f6f1884.setValidateLanguage)(n.lang),_e(n);let i=v9[n.lang]||"en";await __webpack_require__(8817)(`./${i}`),m6.default.locale(i),window.cronLocale=n.cron}catch(e){throw e}}}let _l=["/signin","/signup","/forgot-password","/reset-password"];function _o(e,t){if(!t)return e;let l=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=RegExp(`^${l.replace(/\/?$/,"")}(\\/|$)`);return e.replace(o,"/")||e}function _n(e,t){let l=_o(e,t);return _l.some(e=>l===e||l.startsWith(`${e}/`))}function _i(e,t){let l=_o(e,t);return"/admin"===l||l.startsWith("/admin/")}function _r(e,t){return(e.router.matchRoutes(t)||[]).some(e=>{var t;return(null==e||null==(t=e.route)?void 0:t.authCheck)===!0})}function _a(e,t){return _i(t,e.router.getBasename())||_r(e,t)}function _s(e,t){return _n(t,e.router.getBasename())||e.router.isSkippedAuthCheckRoute(t)?"skipped":_a(e,t)?"required":"unchecked"}let _d=(0,p.createContext)(null);function _u(){return(0,p.useContext)(_d)}function _c(){var e,t;let{allowAnonymous:l}=(0,lg.v6)(),o=(0,u.useFlowEngine)(),n=null==o||null==(t=o.context)||null==(e=t.user)?void 0:e.roles;return(0,p.useMemo)(()=>{let e=e=>{var t;return null==e?"":(null==o||null==(t=o.context)?void 0:t.t)?o.context.t(e):e},t=(n||[]).filter(e=>(null==e?void 0:e.name)!=="__union__").map(t=>({name:t.name,title:e(t.title)}));return l&&t.push({name:"anonymous",title:"Anonymous"}),t},[l,o,n])}_d.displayName="CurrentUserContext";let _p=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),[n,i]=(0,p.useState)(!0),[r,a]=(0,p.useState)(null),d=(0,p.useRef)(!1);if((0,p.useEffect)(()=>{let e=!0,t=l.router.getBasename(),n=_n(o.pathname,t)||l.router.isSkippedAuthCheckRoute(o.pathname),r=_a(l,o.pathname);if(n||!r){i(!1),a(null);return}return d.current||i(!0),a(null),(async()=>{try{await l.dataSourceManager.ensureLoaded(),d.current=!0,e&&i(!1)}catch(t){if(!e)return;i(!1),a(t instanceof Error?t:Error(String(t)))}})(),()=>{e=!1}},[l,o.pathname]),r)throw r;return n?l.renderComponent("AppSpin"):(0,s.jsx)(s.Fragment,{children:t})},_m=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),n=(0,h.useNavigate)(),[i,r]=(0,p.useState)({loading:!0,authStatus:"unknown"}),a=(0,p.useRef)(o);a.current=o;let d=_s(l,o.pathname),c="required"===d&&"authenticated"!==i.authStatus,m=(0,p.useMemo)(()=>({data:i.data,loading:i.loading}),[i.data,i.loading]);if((0,p.useEffect)(()=>{let e=!0;return"required"!==d?void r({loading:!1,authStatus:"unauthenticated",error:null}):(r(e=>"authenticated"===e.authStatus?e:{data:e.data,loading:!0,authStatus:"unknown",error:null}),(async()=>{var t,o;try{let o=await l.apiClient.request({url:"/auth:check",skipNotify:!0,skipAuth:!0});if(!e)return;let i=null==o||null==(t=o.data)?void 0:t.data;if((null==i?void 0:i.code)===302)return void r({loading:!1,authStatus:"redirecting",error:null});if((null==i?void 0:i.id)==null){r({loading:!0,authStatus:"unauthenticated",error:null}),n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});return}let s=(0,u.createCollectionContextMeta)(()=>{var e,t;return(null==(t=l.flowEngine.context.dataSourceManager)||null==(e=t.getDataSource("main"))?void 0:e.getCollection("users"))||null},l.flowEngine.translate("Current user"));s.sort=1e3,l.flowEngine.context.defineProperty("user",{value:i,resolveOnServer:!0,meta:s}),r({data:null==o?void 0:o.data,loading:!1,authStatus:"authenticated",error:null})}catch(i){if(!e)return;let t=i;if((null==t||null==(o=t.response)?void 0:o.status)===401||(null==t?void 0:t.status)===401){r({loading:!0,authStatus:"unauthenticated",error:null}),n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});return}r({loading:!1,authStatus:"unknown",error:i instanceof Error?i:Error(String(i))})}})(),()=>{e=!1})},[l,d,n]),i.error)throw i.error;return i.loading||c?l.renderComponent("AppSpin"):(0,s.jsx)(_d.Provider,{value:m,children:t})},_h=()=>{var e,t;let l=(0,f.n)(),o=!!(null==l||null==(t=l.apiClient)||null==(e=t.auth)?void 0:e.token),n=eP(l);return o?(0,s.jsx)(h.Navigate,{replace:!0,to:"/admin"}):(0,s.jsx)(h.Navigate,{replace:!0,to:`/signin?redirect=${encodeURIComponent(n)}`})};class _f extends iz{async afterAdd(){await this.addPlugins()}async load(){this.addComponents(),this.addRoutes(),this.app.use(_m),this.app.use(_p),this.app.flowEngine.registerModels({AdminLayoutModel:oV,AdminLayoutMenuItemModel:t9,AdminSettingsLayoutModel:v8.C}),this.app.layoutManager.registerLayout({routeName:"admin",routePath:"/admin",uid:eX,layoutModelClass:"AdminLayoutModel"}),this.app.pluginSettingsManager.addMenuItem({key:"plugin-manager",title:this.app.i18n.t("Plugin manager"),icon:"ApiOutlined",aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"plugin-manager",key:"index",title:this.app.i18n.t("Plugin manager"),componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,9784)),aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addMenuItem({key:"system-settings",title:this.app.i18n.t("System settings"),icon:"SettingOutlined",aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"system-settings",key:"index",title:this.app.i18n.t("System settings"),componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,65)),aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addMenuItem({key:"security",title:this.app.i18n.t("Security"),icon:"SafetyOutlined",aclSnippet:"pm.security"})}addRoutes(){this.router.add("root",{path:"/",element:(0,s.jsx)(_h,{})}),this.router.add("not-found",{path:"*",Component:I.bM}),this.router.add("admin.settings",{path:"/admin/settings",componentLoader:()=>Promise.resolve().then(__webpack_require__.bind(__webpack_require__,9652))}),this.router.add("admin.settings.route-empty",{path:"*",Component:h.Outlet})}addComponents(){}async addPlugins(){await this.app.pm.add(v6),await this.app.pm.add(_t,{name:"builtin-locale"})}}var _g=__webpack_require__(5026);let _y={type:"boolean","x-content":'{{t("Unique")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},_v={type:"boolean","x-content":'{{t("Primary")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},__={type:"boolean",title:'{{t("Auto increment")}}',"x-content":'{{t("Auto increment")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly }}"},_b={type:"boolean",title:'{{t("Default value")}}',"x-content":'{{t("Automatically generate default values")}}',"x-decorator":"FormItem","x-component":"Checkbox",default:!0},_x={type:"string",title:'{{t("Relationship type")}}',required:!0,"x-disabled":!0,"x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('HasOne')}}",value:"hasOne"},{label:"{{t('HasMany')}}",value:"hasMany"},{label:"{{t('BelongsTo')}}",value:"belongsTo"},{label:"{{t('BelongsToMany')}}",value:"belongsToMany"}]},_M={onDelete:{type:"string",title:'{{t("ON DELETE")}}',required:!0,default:"SET NULL","x-disabled":"{{ !createOnly }}","x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('SET NULL')}}",value:"SET NULL"},{label:"{{t('RESTRICT')}}",value:"RESTRICT"},{label:"{{t('CASCADE')}}",value:"CASCADE"},{label:"{{t('NO ACTION')}}",value:"NO ACTION"}]}},_w={reverse:{type:"void","x-component":"div",properties:{autoCreateReverseField:{type:"boolean",default:!1,"x-decorator":"FormItem","x-component":"Checkbox","x-content":'{{t("Create inverse field in the target collection")}}'},"reverseField.type":{..._x,title:'{{t("Inverse relationship type")}}'},"reverseField.uiSchema.title":{type:"string",title:'{{t("Inverse field display name")}}',default:"{{record.title}}",required:!0,"x-decorator":"FormItem","x-component":"Input","x-disabled":"{{ !showReverseFieldConfig }}"},"reverseField.name":{type:"string",title:'{{t("Inverse field name")}}',required:!0,"x-decorator":"FormItem","x-component":"Input","x-validator":"uid","x-disabled":"{{ !showReverseFieldConfig }}",description:"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}"}}}},_S={"uiSchema.x-component-props.picker":{type:"string",title:'{{t("Picker")}}',"x-decorator":"FormItem","x-component":"Radio.Group",default:"date",enum:[{label:'{{t("Date")}}',value:"date"},{label:'{{t("Month")}}',value:"month"},{label:'{{t("Quarter")}}',value:"quarter"},{label:'{{t("Year")}}',value:"year"}]},"uiSchema.x-component-props.dateFormat":{type:"string",title:'{{t("Date format")}}',"x-decorator":"FormItem","x-component":"ExpiresRadio","x-decorator-props":{},"x-component-props":{className:(0,S.css)`
|
|
1244
1244
|
.ant-radio-wrapper {
|
|
1245
1245
|
display: flex;
|
|
1246
1246
|
margin: 5px 0px;
|
package/lib/index.js
CHANGED
|
@@ -1240,7 +1240,7 @@ ctx.render(<JsItem />);
|
|
|
1240
1240
|
border-top-color: transparent;
|
|
1241
1241
|
background-color: transparent;
|
|
1242
1242
|
}
|
|
1243
|
-
`,children:"x"})})})]})};class vZ{render(e,t){if(!e)return null;try{return(0,s.jsx)(vU,{value:e,...t})}catch(e){return console.error("渲染失败:",e),(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 渲染错误:",e.message]})}}edit(e){try{return(0,s.jsx)(vQ,{...e})}catch(e){return(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 编辑器加载错误:",e.message]})}}}class v0 extends liquidjs__rspack_import_80.Liquid{transformLiquidContext(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t={};for(let l of e){let e=l.replace(/^ctx\./,"").split("."),o=t;for(let t=0;t<e.length;t++){let n=e[t];t===e.length-1?o[n]=`{{${l}}}`:(o[n]=o[n]||{},o=o[n])}}return t}async render(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};try{return await this.parseAndRender(e,t)}catch(e){return console.error("[Liquid] 模板解析失败:",e),`<pre style="color:red;">Liquid 模板错误:${e.message}</pre>`}}isFieldUsed(e,t){return t.some(t=>t.replace(/^ctx\./,"").endsWith(e))}enrichArrayFieldsSelective(e,t){if(e&&"object"==typeof e)for(let l in e){let o=e[l];if(Array.isArray(o)&&o.length&&"object"==typeof o[0]){let e=o;Object.keys(e[0]).filter(o=>["string","number","boolean"].includes(typeof e[0][o])&&this.isFieldUsed(`${l}.${o}`,t)).forEach(t=>{e[t]=e.map(e=>null!=e[t]?e[t]:"").join(",")}),e.forEach(e=>this.enrichArrayFieldsSelective(e,t))}else o&&"object"==typeof o&&this.enrichArrayFieldsSelective(o,t)}}async renderWithFullContext(e,t){if(e)try{"number"==typeof e&&(e=String(e)),e=e.replace(/\{\{\s*t\s*\(\s*(['"])([\s\S]*?)\1\s*(?:,\s*\{\s*ns\s*:\s*(['"])([\s\S]*?)\3\s*\}\s*)?\)\s*\}\}/g,(e,l,o,n,i)=>{try{let e=i?t.t(o,{ns:i}):t.t(o);if(null==e)return"";return/[{][{%]/.test(e)?`{% raw %}${e}{% endraw %}`:e}catch{return e}});let l=await this.fullVariables(e),o=l.map(e=>this.transformLiquidContext([e])),n=(await Promise.all(o.map(e=>t.resolveJsonTemplate(e)))).reduce((e,t)=>(0,c.merge)(e,t),{});return this.enrichArrayFieldsSelective(n,l),await this.render(e,{ctx:n})}catch(t){return e}}constructor(e){super({extname:".liquid",cache:!0,...e}),this.registerFilter("t",e.ctx.t),this.registerFilter("log",e=>(console.log("[Liquid log]",e),e))}}let v1=()=>{let e=(0,u.useFlowEngine)({throwError:!1});if(!e)return{isMobileLayout:!1,setIsMobileLayout:()=>{}};let t=e.getModel(eX);return t?{isMobileLayout:t.isMobileLayout,setIsMobileLayout:t.setIsMobileLayout.bind(t)}:{isMobileLayout:!1,setIsMobileLayout:()=>{}}};function v2(e){let{flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n}=e;return o$({flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n,getLayoutModel:e=>oq(e,{required:!0})})}var v5=__nested_rspack_require_1176521__(9652),v8=__nested_rspack_require_1176521__(6681),v4=__nested_rspack_require_1176521__(9784),v3=__nested_rspack_require_1176521__(65);class v6 extends iz{async load(){this.app.addComponents({FlowRoute:oX}),this.app.flowEngine.setModelRepository(new vS(this.app));let e=Object.fromEntries(Object.entries(l).filter(e=>{let[,t]=e;return"function"==typeof t&&t.prototype instanceof u.FlowModel}));this.flowEngine.registerModels(e),this.flowEngine.registerActions(o),this.flowEngine.registerActions(t),this.flowEngine.flowSettings.registerComponents({IconPicker:ed.ar,DefaultValue:vM,FlowSettingsVariableTextArea:iK.n}),this.flowEngine.flowSettings.addToolbarItem({key:"dynamic-flows-editor",component:vA,visible:e=>e.getEvents().size>0,sort:0});let n=new vZ;this.flowEngine.context.defineProperty("markdown",{get:()=>n});let i=new v0({ctx:this.flowEngine.context});this.flowEngine.context.defineProperty("liquid",{get:()=>i}),this.flowEngine.context.defineMethod("previewRunJS",async function(e,t){let l=await Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,426));return await l.previewRunJS(String(e??""),this,{version:t})},{description:"Preview/diagnose a RunJS snippet (lint + sandbox execution).",detail:"(code: string, version?: string) => Promise<{ success: boolean; message: string }>",params:[{name:"code",type:"string",description:"RunJS code to preview."},{name:"version",type:"string",description:"RunJS version override (e.g. v1/v2)."}],returns:{type:"Promise<PreviewRunJSResult>",description:"Preview result."},completion:{insertText:"await ctx.previewRunJS('console.log(1)', 'v2')"}})}}let v9={"ar-EG":"ar","az-AZ":"az","bg-BG":"bg","bn-BD":"bn-bd","by-BY":"en","ca-ES":"ca","cs-CZ":"cs","da-DK":"da","de-DE":"de","el-GR":"el","en-GB":"en-gb","en-US":"en","es-ES":"es","et-EE":"et","fa-IR":"fa","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-FR":"fr","ga-IE":"ga","gl-ES":"gl","he-IL":"he","hi-IN":"hi","hr-HR":"hr","hu-HU":"hu","hy-AM":"hy-am","id-ID":"id","is-IS":"is","it-IT":"it","ja-JP":"ja","ka-GE":"ka","kk-KZ":"kk","km-KH":"km","kn-IN":"kn","ko-KR":"ko","ku-IQ":"ku","lt-LT":"lt","lv-LV":"lv","mk-MK":"mk","ml-IN":"ml","mn-MN":"mn","ms-MY":"ms","nb-NO":"nb","ne-NP":"ne","nl-BE":"nl-be","nl-NL":"nl","pl-PL":"pl","pt-BR":"pt-br","pt-PT":"pt","ro-RO":"ro","ru-RU":"ru","si-LK":"si","sk-SK":"sk","sl-SI":"sl","sr-RS":"sr","sv-SE":"sv","ta-IN":"ta","th-TH":"th","tk-TK":"tk","tr-TR":"tr","uk-UA":"uk","ur-PK":"ur","vi-VN":"vi","zh-CN":"zh-cn","zh-HK":"zh-hk","zh-TW":"zh-tw"};class v7{atX0SecondsPastTheMinuteGt20(){return this.data.atX0SecondsPastTheMinuteGt20}atX0MinutesPastTheHourGt20(){return this.data.atX0MinutesPastTheHourGt20}commaMonthX0ThroughMonthX1(){return this.data.commaMonthX0ThroughMonthX1}commaYearX0ThroughYearX1(){return this.data.commaYearX0ThroughYearX1}use24HourTimeFormatByDefault(){return this.data.use24HourTimeFormatByDefault}anErrorOccuredWhenGeneratingTheExpressionD(){return this.data.anErrorOccuredWhenGeneratingTheExpressionD}everyMinute(){return this.data.everyMinute}everyHour(){return this.data.everyHour}atSpace(){return this.data.atSpace}everyMinuteBetweenX0AndX1(){return this.data.everyMinuteBetweenX0AndX1}at(){return this.data.at}spaceAnd(){return this.data.spaceAnd}everySecond(){return this.data.everySecond}everyX0Seconds(){return this.data.everyX0Seconds}secondsX0ThroughX1PastTheMinute(){return this.data.secondsX0ThroughX1PastTheMinute}atX0SecondsPastTheMinute(){return this.data.atX0SecondsPastTheMinute}everyX0Minutes(){return this.data.everyX0Minutes}minutesX0ThroughX1PastTheHour(){return this.data.minutesX0ThroughX1PastTheHour}atX0MinutesPastTheHour(){return this.data.atX0MinutesPastTheHour}everyX0Hours(){return this.data.everyX0Hours}betweenX0AndX1(){return this.data.betweenX0AndX1}atX0(){return this.data.atX0}commaEveryDay(){return this.data.commaEveryDay}commaEveryX0DaysOfTheWeek(){return this.data.commaEveryX0DaysOfTheWeek}commaX0ThroughX1(){return this.data.commaX0ThroughX1}commaAndX0ThroughX1(){return this.data.commaAndX0ThroughX1}first(){return this.data.first}second(){return this.data.second}third(){return this.data.third}fourth(){return this.data.fourth}fifth(){return this.data.fifth}commaOnThe(){return this.data.commaOnThe}spaceX0OfTheMonth(){return this.data.spaceX0OfTheMonth}lastDay(){return this.data.lastDay}commaOnTheLastX0OfTheMonth(){return this.data.commaOnTheLastX0OfTheMonth}commaOnlyOnX0(){return this.data.commaOnlyOnX0}commaAndOnX0(){return this.data.commaAndOnX0}commaEveryX0Months(){return this.data.commaEveryX0Months}commaOnlyInX0(){return this.data.commaOnlyInX0}commaOnTheLastDayOfTheMonth(){return this.data.commaOnTheLastDayOfTheMonth}commaOnTheLastWeekdayOfTheMonth(){return this.data.commaOnTheLastWeekdayOfTheMonth}commaDaysBeforeTheLastDayOfTheMonth(){return this.data.commaDaysBeforeTheLastDayOfTheMonth}firstWeekday(){return this.data.firstWeekday}weekdayNearestDayX0(){return this.data.weekdayNearestDayX0}commaOnTheX0OfTheMonth(){return this.data.commaOnTheX0OfTheMonth}commaEveryX0Days(){return this.data.commaEveryX0Days}commaBetweenDayX0AndX1OfTheMonth(){return this.data.commaBetweenDayX0AndX1OfTheMonth}commaOnDayX0OfTheMonth(){return this.data.commaOnDayX0OfTheMonth}commaEveryHour(){return this.data.commaEveryHour}commaEveryX0Years(){return this.data.commaEveryX0Years}commaStartingX0(){return this.data.commaStartingX0}daysOfTheWeek(){return this.data.daysOfTheWeek}monthsOfTheYear(){return this.data.monthsOfTheYear}constructor(e){this.data=e}}let be=e=>{(cronstrue__rspack_import_82_default().default?cronstrue__rspack_import_82_default().default:cronstrue__rspack_import_82_default()).initialize({load(t){t[null==e?void 0:e.lang]=new v7(null==e?void 0:e.cronstrue)}})};class bt extends iz{async afterAdd(){let e=this.app.apiClient,t=e.auth.locale;try{var l;let o=await e.request({url:"app:getLang",params:{locale:t},headers:{"X-Role":"anonymous"}}),n=(null==o||null==(l=o.data)?void 0:l.data)||{};this.engine.context.defineProperty("locales",{value:n}),this.app.use(g.App,{component:!1}),n.lang&&(e.auth.setLocale(n.lang),this.app.setDocumentLanguage(n.lang),this.app.i18n.changeLanguage(n.lang)),Object.keys(n.resources||{}).forEach(e=>{this.app.i18n.addResources(n.lang,e,n.resources[e]||{})}),(0,_formily_validator__rspack_import_81.setValidateLanguage)(n.lang),be(n);let i=v9[n.lang]||"en";await __nested_rspack_require_1176521__(8817)(`./${i}`),m6.default.locale(i),window.cronLocale=n.cron}catch(e){throw e}}}let bl=["/signin","/signup","/forgot-password","/reset-password"];function bo(e,t){if(!t)return e;let l=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=RegExp(`^${l.replace(/\/?$/,"")}(\\/|$)`);return e.replace(o,"/")||e}function bn(e,t){let l=bo(e,t);return bl.some(e=>l===e||l.startsWith(`${e}/`))}function bi(e,t){let l=bo(e,t);return"/admin"===l||l.startsWith("/admin/")}function br(e,t){return(e.router.matchRoutes(t)||[]).some(e=>{var t;return(null==e||null==(t=e.route)?void 0:t.authCheck)===!0})}function ba(e,t){return bi(t,e.router.getBasename())||br(e,t)}function bs(e,t){return bn(t,e.router.getBasename())||e.router.isSkippedAuthCheckRoute(t)?"skipped":ba(e,t)?"required":"unchecked"}let bd=(0,p.createContext)(null);function bu(){return(0,p.useContext)(bd)}function bc(){var e,t;let{allowAnonymous:l}=(0,lg.v6)(),o=(0,u.useFlowEngine)(),n=null==o||null==(t=o.context)||null==(e=t.user)?void 0:e.roles;return(0,p.useMemo)(()=>{let e=e=>{var t;return null==e?"":(null==o||null==(t=o.context)?void 0:t.t)?o.context.t(e):e},t=(n||[]).filter(e=>(null==e?void 0:e.name)!=="__union__").map(t=>({name:t.name,title:e(t.title)}));return l&&t.push({name:"anonymous",title:"Anonymous"}),t},[l,o,n])}bd.displayName="CurrentUserContext";let bp=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),[n,i]=(0,p.useState)(!0),[r,a]=(0,p.useState)(null),d=(0,p.useRef)(!1);if((0,p.useEffect)(()=>{let e=!0,t=l.router.getBasename(),n=bn(o.pathname,t)||l.router.isSkippedAuthCheckRoute(o.pathname),r=ba(l,o.pathname);if(n||!r){i(!1),a(null);return}return d.current||i(!0),a(null),(async()=>{try{await l.dataSourceManager.ensureLoaded(),d.current=!0,e&&i(!1)}catch(t){if(!e)return;i(!1),a(t instanceof Error?t:Error(String(t)))}})(),()=>{e=!1}},[l,o.pathname]),r)throw r;return n?l.renderComponent("AppSpin"):(0,s.jsx)(s.Fragment,{children:t})},bm=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),n=(0,h.useNavigate)(),[i,r]=(0,p.useState)({loading:!0}),a=(0,p.useRef)(o);a.current=o;let d=bs(l,o.pathname);return((0,p.useEffect)(()=>{let e=!0;return"required"!==d?void r({loading:!1}):(r(e=>e.loading?e:{...e,loading:!0}),(async()=>{var t,o;try{let o=await l.apiClient.request({url:"/auth:check",skipNotify:!0,skipAuth:!0});if(!e)return;let i=null==o||null==(t=o.data)?void 0:t.data;if((null==i?void 0:i.code)===302)return void r({loading:!1});if((null==i?void 0:i.id)==null)return void n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});let s=(0,u.createCollectionContextMeta)(()=>{var e,t;return(null==(t=l.flowEngine.context.dataSourceManager)||null==(e=t.getDataSource("main"))?void 0:e.getCollection("users"))||null},l.flowEngine.translate("Current user"));s.sort=1e3,l.flowEngine.context.defineProperty("user",{value:i,resolveOnServer:!0,meta:s}),r({data:null==o?void 0:o.data,loading:!1})}catch(t){if(!e)return;if((null==t||null==(o=t.response)?void 0:o.status)===401||(null==t?void 0:t.status)===401)return void n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});throw r({loading:!1}),t}})(),()=>{e=!1})},[l,d,n]),i.loading)?l.renderComponent("AppSpin"):(0,s.jsx)(bd.Provider,{value:i,children:t})},bh=()=>{var e,t;let l=(0,f.n)(),o=!!(null==l||null==(t=l.apiClient)||null==(e=t.auth)?void 0:e.token),n=eP(l);return o?(0,s.jsx)(h.Navigate,{replace:!0,to:"/admin"}):(0,s.jsx)(h.Navigate,{replace:!0,to:`/signin?redirect=${encodeURIComponent(n)}`})};class bf extends iz{async afterAdd(){await this.addPlugins()}async load(){this.addComponents(),this.addRoutes(),this.app.use(bp),this.app.use(bm),this.app.flowEngine.registerModels({AdminLayoutModel:oH,AdminLayoutMenuItemModel:t9,AdminSettingsLayoutModel:v8.C}),this.app.layoutManager.registerLayout({routeName:"admin",routePath:"/admin",uid:eX,layoutModelClass:"AdminLayoutModel"}),this.app.pluginSettingsManager.addMenuItem({key:"plugin-manager",title:this.app.i18n.t("Plugin manager"),icon:"ApiOutlined",aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"plugin-manager",key:"index",title:this.app.i18n.t("Plugin manager"),componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,9784)),aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addMenuItem({key:"system-settings",title:this.app.i18n.t("System settings"),icon:"SettingOutlined",aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"system-settings",key:"index",title:this.app.i18n.t("System settings"),componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,65)),aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addMenuItem({key:"security",title:this.app.i18n.t("Security"),icon:"SafetyOutlined",aclSnippet:"pm.security"})}addRoutes(){this.router.add("root",{path:"/",element:(0,s.jsx)(bh,{})}),this.router.add("not-found",{path:"*",Component:j.bM}),this.router.add("admin.settings",{path:"/admin/settings",componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,9652))}),this.router.add("admin.settings.route-empty",{path:"*",Component:h.Outlet})}addComponents(){}async addPlugins(){await this.app.pm.add(v6),await this.app.pm.add(bt,{name:"builtin-locale"})}}var bg=__nested_rspack_require_1176521__(5026);let by={type:"boolean","x-content":'{{t("Unique")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},bv={type:"boolean","x-content":'{{t("Primary")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},bb={type:"boolean",title:'{{t("Auto increment")}}',"x-content":'{{t("Auto increment")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly }}"},bx={type:"boolean",title:'{{t("Default value")}}',"x-content":'{{t("Automatically generate default values")}}',"x-decorator":"FormItem","x-component":"Checkbox",default:!0},bM={type:"string",title:'{{t("Relationship type")}}',required:!0,"x-disabled":!0,"x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('HasOne')}}",value:"hasOne"},{label:"{{t('HasMany')}}",value:"hasMany"},{label:"{{t('BelongsTo')}}",value:"belongsTo"},{label:"{{t('BelongsToMany')}}",value:"belongsToMany"}]},b_={onDelete:{type:"string",title:'{{t("ON DELETE")}}',required:!0,default:"SET NULL","x-disabled":"{{ !createOnly }}","x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('SET NULL')}}",value:"SET NULL"},{label:"{{t('RESTRICT')}}",value:"RESTRICT"},{label:"{{t('CASCADE')}}",value:"CASCADE"},{label:"{{t('NO ACTION')}}",value:"NO ACTION"}]}},bS={reverse:{type:"void","x-component":"div",properties:{autoCreateReverseField:{type:"boolean",default:!1,"x-decorator":"FormItem","x-component":"Checkbox","x-content":'{{t("Create inverse field in the target collection")}}'},"reverseField.type":{...bM,title:'{{t("Inverse relationship type")}}'},"reverseField.uiSchema.title":{type:"string",title:'{{t("Inverse field display name")}}',default:"{{record.title}}",required:!0,"x-decorator":"FormItem","x-component":"Input","x-disabled":"{{ !showReverseFieldConfig }}"},"reverseField.name":{type:"string",title:'{{t("Inverse field name")}}',required:!0,"x-decorator":"FormItem","x-component":"Input","x-validator":"uid","x-disabled":"{{ !showReverseFieldConfig }}",description:"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}"}}}},bw={"uiSchema.x-component-props.picker":{type:"string",title:'{{t("Picker")}}',"x-decorator":"FormItem","x-component":"Radio.Group",default:"date",enum:[{label:'{{t("Date")}}',value:"date"},{label:'{{t("Month")}}',value:"month"},{label:'{{t("Quarter")}}',value:"quarter"},{label:'{{t("Year")}}',value:"year"}]},"uiSchema.x-component-props.dateFormat":{type:"string",title:'{{t("Date format")}}',"x-decorator":"FormItem","x-component":"ExpiresRadio","x-decorator-props":{},"x-component-props":{className:(0,w.css)`
|
|
1243
|
+
`,children:"x"})})})]})};class vZ{render(e,t){if(!e)return null;try{return(0,s.jsx)(vU,{value:e,...t})}catch(e){return console.error("渲染失败:",e),(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 渲染错误:",e.message]})}}edit(e){try{return(0,s.jsx)(vQ,{...e})}catch(e){return(0,s.jsxs)("pre",{style:{color:"red"},children:["Markdown 编辑器加载错误:",e.message]})}}}class v0 extends liquidjs__rspack_import_80.Liquid{transformLiquidContext(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t={};for(let l of e){let e=l.replace(/^ctx\./,"").split("."),o=t;for(let t=0;t<e.length;t++){let n=e[t];t===e.length-1?o[n]=`{{${l}}}`:(o[n]=o[n]||{},o=o[n])}}return t}async render(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};try{return await this.parseAndRender(e,t)}catch(e){return console.error("[Liquid] 模板解析失败:",e),`<pre style="color:red;">Liquid 模板错误:${e.message}</pre>`}}isFieldUsed(e,t){return t.some(t=>t.replace(/^ctx\./,"").endsWith(e))}enrichArrayFieldsSelective(e,t){if(e&&"object"==typeof e)for(let l in e){let o=e[l];if(Array.isArray(o)&&o.length&&"object"==typeof o[0]){let e=o;Object.keys(e[0]).filter(o=>["string","number","boolean"].includes(typeof e[0][o])&&this.isFieldUsed(`${l}.${o}`,t)).forEach(t=>{e[t]=e.map(e=>null!=e[t]?e[t]:"").join(",")}),e.forEach(e=>this.enrichArrayFieldsSelective(e,t))}else o&&"object"==typeof o&&this.enrichArrayFieldsSelective(o,t)}}async renderWithFullContext(e,t){if(e)try{"number"==typeof e&&(e=String(e)),e=e.replace(/\{\{\s*t\s*\(\s*(['"])([\s\S]*?)\1\s*(?:,\s*\{\s*ns\s*:\s*(['"])([\s\S]*?)\3\s*\}\s*)?\)\s*\}\}/g,(e,l,o,n,i)=>{try{let e=i?t.t(o,{ns:i}):t.t(o);if(null==e)return"";return/[{][{%]/.test(e)?`{% raw %}${e}{% endraw %}`:e}catch{return e}});let l=await this.fullVariables(e),o=l.map(e=>this.transformLiquidContext([e])),n=(await Promise.all(o.map(e=>t.resolveJsonTemplate(e)))).reduce((e,t)=>(0,c.merge)(e,t),{});return this.enrichArrayFieldsSelective(n,l),await this.render(e,{ctx:n})}catch(t){return e}}constructor(e){super({extname:".liquid",cache:!0,...e}),this.registerFilter("t",e.ctx.t),this.registerFilter("log",e=>(console.log("[Liquid log]",e),e))}}let v1=()=>{let e=(0,u.useFlowEngine)({throwError:!1});if(!e)return{isMobileLayout:!1,setIsMobileLayout:()=>{}};let t=e.getModel(eX);return t?{isMobileLayout:t.isMobileLayout,setIsMobileLayout:t.setIsMobileLayout.bind(t)}:{isMobileLayout:!1,setIsMobileLayout:()=>{}}};function v2(e){let{flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n}=e;return o$({flowEngine:t,pageUid:l,refreshDesktopRoutes:o,layoutContentRef:n,getLayoutModel:e=>oq(e,{required:!0})})}var v5=__nested_rspack_require_1176521__(9652),v8=__nested_rspack_require_1176521__(6681),v4=__nested_rspack_require_1176521__(9784),v3=__nested_rspack_require_1176521__(65);class v6 extends iz{async load(){this.app.addComponents({FlowRoute:oX}),this.app.flowEngine.setModelRepository(new vS(this.app));let e=Object.fromEntries(Object.entries(l).filter(e=>{let[,t]=e;return"function"==typeof t&&t.prototype instanceof u.FlowModel}));this.flowEngine.registerModels(e),this.flowEngine.registerActions(o),this.flowEngine.registerActions(t),this.flowEngine.flowSettings.registerComponents({IconPicker:ed.ar,DefaultValue:vM,FlowSettingsVariableTextArea:iK.n}),this.flowEngine.flowSettings.addToolbarItem({key:"dynamic-flows-editor",component:vA,visible:e=>e.getEvents().size>0,sort:0});let n=new vZ;this.flowEngine.context.defineProperty("markdown",{get:()=>n});let i=new v0({ctx:this.flowEngine.context});this.flowEngine.context.defineProperty("liquid",{get:()=>i}),this.flowEngine.context.defineMethod("previewRunJS",async function(e,t){let l=await Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,426));return await l.previewRunJS(String(e??""),this,{version:t})},{description:"Preview/diagnose a RunJS snippet (lint + sandbox execution).",detail:"(code: string, version?: string) => Promise<{ success: boolean; message: string }>",params:[{name:"code",type:"string",description:"RunJS code to preview."},{name:"version",type:"string",description:"RunJS version override (e.g. v1/v2)."}],returns:{type:"Promise<PreviewRunJSResult>",description:"Preview result."},completion:{insertText:"await ctx.previewRunJS('console.log(1)', 'v2')"}})}}let v9={"ar-EG":"ar","az-AZ":"az","bg-BG":"bg","bn-BD":"bn-bd","by-BY":"en","ca-ES":"ca","cs-CZ":"cs","da-DK":"da","de-DE":"de","el-GR":"el","en-GB":"en-gb","en-US":"en","es-ES":"es","et-EE":"et","fa-IR":"fa","fi-FI":"fi","fr-BE":"fr","fr-CA":"fr","fr-FR":"fr","ga-IE":"ga","gl-ES":"gl","he-IL":"he","hi-IN":"hi","hr-HR":"hr","hu-HU":"hu","hy-AM":"hy-am","id-ID":"id","is-IS":"is","it-IT":"it","ja-JP":"ja","ka-GE":"ka","kk-KZ":"kk","km-KH":"km","kn-IN":"kn","ko-KR":"ko","ku-IQ":"ku","lt-LT":"lt","lv-LV":"lv","mk-MK":"mk","ml-IN":"ml","mn-MN":"mn","ms-MY":"ms","nb-NO":"nb","ne-NP":"ne","nl-BE":"nl-be","nl-NL":"nl","pl-PL":"pl","pt-BR":"pt-br","pt-PT":"pt","ro-RO":"ro","ru-RU":"ru","si-LK":"si","sk-SK":"sk","sl-SI":"sl","sr-RS":"sr","sv-SE":"sv","ta-IN":"ta","th-TH":"th","tk-TK":"tk","tr-TR":"tr","uk-UA":"uk","ur-PK":"ur","vi-VN":"vi","zh-CN":"zh-cn","zh-HK":"zh-hk","zh-TW":"zh-tw"};class v7{atX0SecondsPastTheMinuteGt20(){return this.data.atX0SecondsPastTheMinuteGt20}atX0MinutesPastTheHourGt20(){return this.data.atX0MinutesPastTheHourGt20}commaMonthX0ThroughMonthX1(){return this.data.commaMonthX0ThroughMonthX1}commaYearX0ThroughYearX1(){return this.data.commaYearX0ThroughYearX1}use24HourTimeFormatByDefault(){return this.data.use24HourTimeFormatByDefault}anErrorOccuredWhenGeneratingTheExpressionD(){return this.data.anErrorOccuredWhenGeneratingTheExpressionD}everyMinute(){return this.data.everyMinute}everyHour(){return this.data.everyHour}atSpace(){return this.data.atSpace}everyMinuteBetweenX0AndX1(){return this.data.everyMinuteBetweenX0AndX1}at(){return this.data.at}spaceAnd(){return this.data.spaceAnd}everySecond(){return this.data.everySecond}everyX0Seconds(){return this.data.everyX0Seconds}secondsX0ThroughX1PastTheMinute(){return this.data.secondsX0ThroughX1PastTheMinute}atX0SecondsPastTheMinute(){return this.data.atX0SecondsPastTheMinute}everyX0Minutes(){return this.data.everyX0Minutes}minutesX0ThroughX1PastTheHour(){return this.data.minutesX0ThroughX1PastTheHour}atX0MinutesPastTheHour(){return this.data.atX0MinutesPastTheHour}everyX0Hours(){return this.data.everyX0Hours}betweenX0AndX1(){return this.data.betweenX0AndX1}atX0(){return this.data.atX0}commaEveryDay(){return this.data.commaEveryDay}commaEveryX0DaysOfTheWeek(){return this.data.commaEveryX0DaysOfTheWeek}commaX0ThroughX1(){return this.data.commaX0ThroughX1}commaAndX0ThroughX1(){return this.data.commaAndX0ThroughX1}first(){return this.data.first}second(){return this.data.second}third(){return this.data.third}fourth(){return this.data.fourth}fifth(){return this.data.fifth}commaOnThe(){return this.data.commaOnThe}spaceX0OfTheMonth(){return this.data.spaceX0OfTheMonth}lastDay(){return this.data.lastDay}commaOnTheLastX0OfTheMonth(){return this.data.commaOnTheLastX0OfTheMonth}commaOnlyOnX0(){return this.data.commaOnlyOnX0}commaAndOnX0(){return this.data.commaAndOnX0}commaEveryX0Months(){return this.data.commaEveryX0Months}commaOnlyInX0(){return this.data.commaOnlyInX0}commaOnTheLastDayOfTheMonth(){return this.data.commaOnTheLastDayOfTheMonth}commaOnTheLastWeekdayOfTheMonth(){return this.data.commaOnTheLastWeekdayOfTheMonth}commaDaysBeforeTheLastDayOfTheMonth(){return this.data.commaDaysBeforeTheLastDayOfTheMonth}firstWeekday(){return this.data.firstWeekday}weekdayNearestDayX0(){return this.data.weekdayNearestDayX0}commaOnTheX0OfTheMonth(){return this.data.commaOnTheX0OfTheMonth}commaEveryX0Days(){return this.data.commaEveryX0Days}commaBetweenDayX0AndX1OfTheMonth(){return this.data.commaBetweenDayX0AndX1OfTheMonth}commaOnDayX0OfTheMonth(){return this.data.commaOnDayX0OfTheMonth}commaEveryHour(){return this.data.commaEveryHour}commaEveryX0Years(){return this.data.commaEveryX0Years}commaStartingX0(){return this.data.commaStartingX0}daysOfTheWeek(){return this.data.daysOfTheWeek}monthsOfTheYear(){return this.data.monthsOfTheYear}constructor(e){this.data=e}}let be=e=>{(cronstrue__rspack_import_82_default().default?cronstrue__rspack_import_82_default().default:cronstrue__rspack_import_82_default()).initialize({load(t){t[null==e?void 0:e.lang]=new v7(null==e?void 0:e.cronstrue)}})};class bt extends iz{async afterAdd(){let e=this.app.apiClient,t=e.auth.locale;try{var l;let o=await e.request({url:"app:getLang",params:{locale:t},headers:{"X-Role":"anonymous"}}),n=(null==o||null==(l=o.data)?void 0:l.data)||{};this.engine.context.defineProperty("locales",{value:n}),this.app.use(g.App,{component:!1}),n.lang&&(e.auth.setLocale(n.lang),this.app.setDocumentLanguage(n.lang),this.app.i18n.changeLanguage(n.lang)),Object.keys(n.resources||{}).forEach(e=>{this.app.i18n.addResources(n.lang,e,n.resources[e]||{})}),(0,_formily_validator__rspack_import_81.setValidateLanguage)(n.lang),be(n);let i=v9[n.lang]||"en";await __nested_rspack_require_1176521__(8817)(`./${i}`),m6.default.locale(i),window.cronLocale=n.cron}catch(e){throw e}}}let bl=["/signin","/signup","/forgot-password","/reset-password"];function bo(e,t){if(!t)return e;let l=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o=RegExp(`^${l.replace(/\/?$/,"")}(\\/|$)`);return e.replace(o,"/")||e}function bn(e,t){let l=bo(e,t);return bl.some(e=>l===e||l.startsWith(`${e}/`))}function bi(e,t){let l=bo(e,t);return"/admin"===l||l.startsWith("/admin/")}function br(e,t){return(e.router.matchRoutes(t)||[]).some(e=>{var t;return(null==e||null==(t=e.route)?void 0:t.authCheck)===!0})}function ba(e,t){return bi(t,e.router.getBasename())||br(e,t)}function bs(e,t){return bn(t,e.router.getBasename())||e.router.isSkippedAuthCheckRoute(t)?"skipped":ba(e,t)?"required":"unchecked"}let bd=(0,p.createContext)(null);function bu(){return(0,p.useContext)(bd)}function bc(){var e,t;let{allowAnonymous:l}=(0,lg.v6)(),o=(0,u.useFlowEngine)(),n=null==o||null==(t=o.context)||null==(e=t.user)?void 0:e.roles;return(0,p.useMemo)(()=>{let e=e=>{var t;return null==e?"":(null==o||null==(t=o.context)?void 0:t.t)?o.context.t(e):e},t=(n||[]).filter(e=>(null==e?void 0:e.name)!=="__union__").map(t=>({name:t.name,title:e(t.title)}));return l&&t.push({name:"anonymous",title:"Anonymous"}),t},[l,o,n])}bd.displayName="CurrentUserContext";let bp=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),[n,i]=(0,p.useState)(!0),[r,a]=(0,p.useState)(null),d=(0,p.useRef)(!1);if((0,p.useEffect)(()=>{let e=!0,t=l.router.getBasename(),n=bn(o.pathname,t)||l.router.isSkippedAuthCheckRoute(o.pathname),r=ba(l,o.pathname);if(n||!r){i(!1),a(null);return}return d.current||i(!0),a(null),(async()=>{try{await l.dataSourceManager.ensureLoaded(),d.current=!0,e&&i(!1)}catch(t){if(!e)return;i(!1),a(t instanceof Error?t:Error(String(t)))}})(),()=>{e=!1}},[l,o.pathname]),r)throw r;return n?l.renderComponent("AppSpin"):(0,s.jsx)(s.Fragment,{children:t})},bm=e=>{let{children:t}=e,l=(0,f.n)(),o=(0,h.useLocation)(),n=(0,h.useNavigate)(),[i,r]=(0,p.useState)({loading:!0,authStatus:"unknown"}),a=(0,p.useRef)(o);a.current=o;let d=bs(l,o.pathname),c="required"===d&&"authenticated"!==i.authStatus,m=(0,p.useMemo)(()=>({data:i.data,loading:i.loading}),[i.data,i.loading]);if((0,p.useEffect)(()=>{let e=!0;return"required"!==d?void r({loading:!1,authStatus:"unauthenticated",error:null}):(r(e=>"authenticated"===e.authStatus?e:{data:e.data,loading:!0,authStatus:"unknown",error:null}),(async()=>{var t,o;try{let o=await l.apiClient.request({url:"/auth:check",skipNotify:!0,skipAuth:!0});if(!e)return;let i=null==o||null==(t=o.data)?void 0:t.data;if((null==i?void 0:i.code)===302)return void r({loading:!1,authStatus:"redirecting",error:null});if((null==i?void 0:i.id)==null){r({loading:!0,authStatus:"unauthenticated",error:null}),n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});return}let s=(0,u.createCollectionContextMeta)(()=>{var e,t;return(null==(t=l.flowEngine.context.dataSourceManager)||null==(e=t.getDataSource("main"))?void 0:e.getCollection("users"))||null},l.flowEngine.translate("Current user"));s.sort=1e3,l.flowEngine.context.defineProperty("user",{value:i,resolveOnServer:!0,meta:s}),r({data:null==o?void 0:o.data,loading:!1,authStatus:"authenticated",error:null})}catch(i){if(!e)return;let t=i;if((null==t||null==(o=t.response)?void 0:o.status)===401||(null==t?void 0:t.status)===401){r({loading:!0,authStatus:"unauthenticated",error:null}),n(`/signin?redirect=${encodeURIComponent(eT(l,a.current))}`,{replace:!0});return}r({loading:!1,authStatus:"unknown",error:i instanceof Error?i:Error(String(i))})}})(),()=>{e=!1})},[l,d,n]),i.error)throw i.error;return i.loading||c?l.renderComponent("AppSpin"):(0,s.jsx)(bd.Provider,{value:m,children:t})},bh=()=>{var e,t;let l=(0,f.n)(),o=!!(null==l||null==(t=l.apiClient)||null==(e=t.auth)?void 0:e.token),n=eP(l);return o?(0,s.jsx)(h.Navigate,{replace:!0,to:"/admin"}):(0,s.jsx)(h.Navigate,{replace:!0,to:`/signin?redirect=${encodeURIComponent(n)}`})};class bf extends iz{async afterAdd(){await this.addPlugins()}async load(){this.addComponents(),this.addRoutes(),this.app.use(bm),this.app.use(bp),this.app.flowEngine.registerModels({AdminLayoutModel:oH,AdminLayoutMenuItemModel:t9,AdminSettingsLayoutModel:v8.C}),this.app.layoutManager.registerLayout({routeName:"admin",routePath:"/admin",uid:eX,layoutModelClass:"AdminLayoutModel"}),this.app.pluginSettingsManager.addMenuItem({key:"plugin-manager",title:this.app.i18n.t("Plugin manager"),icon:"ApiOutlined",aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"plugin-manager",key:"index",title:this.app.i18n.t("Plugin manager"),componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,9784)),aclSnippet:"pm",sort:-200}),this.app.pluginSettingsManager.addMenuItem({key:"system-settings",title:this.app.i18n.t("System settings"),icon:"SettingOutlined",aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addPageTabItem({menuKey:"system-settings",key:"index",title:this.app.i18n.t("System settings"),componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,65)),aclSnippet:"pm.system-settings.system-settings",sort:-100}),this.app.pluginSettingsManager.addMenuItem({key:"security",title:this.app.i18n.t("Security"),icon:"SafetyOutlined",aclSnippet:"pm.security"})}addRoutes(){this.router.add("root",{path:"/",element:(0,s.jsx)(bh,{})}),this.router.add("not-found",{path:"*",Component:j.bM}),this.router.add("admin.settings",{path:"/admin/settings",componentLoader:()=>Promise.resolve().then(__nested_rspack_require_1176521__.bind(__nested_rspack_require_1176521__,9652))}),this.router.add("admin.settings.route-empty",{path:"*",Component:h.Outlet})}addComponents(){}async addPlugins(){await this.app.pm.add(v6),await this.app.pm.add(bt,{name:"builtin-locale"})}}var bg=__nested_rspack_require_1176521__(5026);let by={type:"boolean","x-content":'{{t("Unique")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},bv={type:"boolean","x-content":'{{t("Primary")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly || primaryKeyOnly }}"},bb={type:"boolean",title:'{{t("Auto increment")}}',"x-content":'{{t("Auto increment")}}',"x-decorator":"FormItem","x-component":"Checkbox","x-disabled":"{{ !createMainOnly }}"},bx={type:"boolean",title:'{{t("Default value")}}',"x-content":'{{t("Automatically generate default values")}}',"x-decorator":"FormItem","x-component":"Checkbox",default:!0},bM={type:"string",title:'{{t("Relationship type")}}',required:!0,"x-disabled":!0,"x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('HasOne')}}",value:"hasOne"},{label:"{{t('HasMany')}}",value:"hasMany"},{label:"{{t('BelongsTo')}}",value:"belongsTo"},{label:"{{t('BelongsToMany')}}",value:"belongsToMany"}]},b_={onDelete:{type:"string",title:'{{t("ON DELETE")}}',required:!0,default:"SET NULL","x-disabled":"{{ !createOnly }}","x-decorator":"FormItem","x-component":"Select",enum:[{label:"{{t('SET NULL')}}",value:"SET NULL"},{label:"{{t('RESTRICT')}}",value:"RESTRICT"},{label:"{{t('CASCADE')}}",value:"CASCADE"},{label:"{{t('NO ACTION')}}",value:"NO ACTION"}]}},bS={reverse:{type:"void","x-component":"div",properties:{autoCreateReverseField:{type:"boolean",default:!1,"x-decorator":"FormItem","x-component":"Checkbox","x-content":'{{t("Create inverse field in the target collection")}}'},"reverseField.type":{...bM,title:'{{t("Inverse relationship type")}}'},"reverseField.uiSchema.title":{type:"string",title:'{{t("Inverse field display name")}}',default:"{{record.title}}",required:!0,"x-decorator":"FormItem","x-component":"Input","x-disabled":"{{ !showReverseFieldConfig }}"},"reverseField.name":{type:"string",title:'{{t("Inverse field name")}}',required:!0,"x-decorator":"FormItem","x-component":"Input","x-validator":"uid","x-disabled":"{{ !showReverseFieldConfig }}",description:"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}"}}}},bw={"uiSchema.x-component-props.picker":{type:"string",title:'{{t("Picker")}}',"x-decorator":"FormItem","x-component":"Radio.Group",default:"date",enum:[{label:'{{t("Date")}}',value:"date"},{label:'{{t("Month")}}',value:"month"},{label:'{{t("Quarter")}}',value:"quarter"},{label:'{{t("Year")}}',value:"year"}]},"uiSchema.x-component-props.dateFormat":{type:"string",title:'{{t("Date format")}}',"x-decorator":"FormItem","x-component":"ExpiresRadio","x-decorator-props":{},"x-component-props":{className:(0,w.css)`
|
|
1244
1244
|
.ant-radio-wrapper {
|
|
1245
1245
|
display: flex;
|
|
1246
1246
|
margin: 5px 0px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/client-v2",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.mjs",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@formily/antd-v5": "1.2.3",
|
|
28
28
|
"@formily/react": "^2.2.27",
|
|
29
29
|
"@formily/shared": "^2.2.27",
|
|
30
|
-
"@nocobase/evaluators": "2.1.
|
|
31
|
-
"@nocobase/flow-engine": "2.1.
|
|
32
|
-
"@nocobase/sdk": "2.1.
|
|
33
|
-
"@nocobase/shared": "2.1.
|
|
34
|
-
"@nocobase/utils": "2.1.
|
|
30
|
+
"@nocobase/evaluators": "2.1.2",
|
|
31
|
+
"@nocobase/flow-engine": "2.1.2",
|
|
32
|
+
"@nocobase/sdk": "2.1.2",
|
|
33
|
+
"@nocobase/shared": "2.1.2",
|
|
34
|
+
"@nocobase/utils": "2.1.2",
|
|
35
35
|
"ahooks": "^3.7.2",
|
|
36
36
|
"antd": "5.24.2",
|
|
37
37
|
"antd-style": "3.7.1",
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"react-i18next": "^11.15.1",
|
|
47
47
|
"react-router-dom": "^6.30.1"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "e1b28561425c5c34ff3bc6ae1f81c66b72f02872"
|
|
50
50
|
}
|
|
@@ -12,6 +12,10 @@ import { act, render, screen, waitFor } from '@testing-library/react';
|
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import { NocoBaseBuildInPlugin } from '../nocobase-buildin-plugin';
|
|
14
14
|
|
|
15
|
+
const TestingAppSpin = () => <div data-testid="app-spin">app spin</div>;
|
|
16
|
+
|
|
17
|
+
const TestingAppError = ({ error }: { error: Error }) => <div role="alert">{error.message}</div>;
|
|
18
|
+
|
|
15
19
|
class SkippedPublicRoutePlugin extends Plugin {
|
|
16
20
|
async load() {
|
|
17
21
|
this.router.add('public', {
|
|
@@ -22,6 +26,31 @@ class SkippedPublicRoutePlugin extends Plugin {
|
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
class DummySigninRoutePlugin extends Plugin {
|
|
30
|
+
async load() {
|
|
31
|
+
this.router.add('signin-test', {
|
|
32
|
+
path: '/signin',
|
|
33
|
+
skipAuthCheck: true,
|
|
34
|
+
Component: () => <div>signin page</div>,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class AuthBootstrapRoutePlugin extends Plugin {
|
|
40
|
+
async load() {
|
|
41
|
+
this.router.add('secure', {
|
|
42
|
+
path: '/secure',
|
|
43
|
+
authCheck: true,
|
|
44
|
+
Component: () => <div>secure page</div>,
|
|
45
|
+
});
|
|
46
|
+
this.router.add('guest', {
|
|
47
|
+
path: '/guest',
|
|
48
|
+
authCheck: false,
|
|
49
|
+
Component: () => <div>guest page</div>,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
25
54
|
describe('nocobase buildin plugin auth redirect', () => {
|
|
26
55
|
const originalLocation = globalThis.window.location;
|
|
27
56
|
|
|
@@ -155,6 +184,176 @@ describe('nocobase buildin plugin auth redirect', () => {
|
|
|
155
184
|
});
|
|
156
185
|
});
|
|
157
186
|
|
|
187
|
+
it('should defer data source bootstrap until auth-required route is authenticated after signin redirect', async () => {
|
|
188
|
+
const app = createMockClient({
|
|
189
|
+
publicPath: '/v2/',
|
|
190
|
+
plugins: [NocoBaseBuildInPlugin as any, DummySigninRoutePlugin as any, AuthBootstrapRoutePlugin as any],
|
|
191
|
+
components: { AppSpin: TestingAppSpin },
|
|
192
|
+
router: { type: 'memory', initialEntries: ['/v2/secure'] },
|
|
193
|
+
});
|
|
194
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
195
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
196
|
+
});
|
|
197
|
+
const events: string[] = [];
|
|
198
|
+
app.apiMock.onGet('/auth:check').replyOnce(() => {
|
|
199
|
+
events.push('auth:first');
|
|
200
|
+
return [200, { data: {} }];
|
|
201
|
+
});
|
|
202
|
+
app.apiMock.onGet('/auth:check').reply(() => {
|
|
203
|
+
events.push('auth:second');
|
|
204
|
+
return [200, { data: { id: 1 } }];
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockImplementation(() => {
|
|
208
|
+
if (!app.apiClient.auth.token) {
|
|
209
|
+
const pending = new Promise<void>(() => undefined);
|
|
210
|
+
app.dataSourceManager.loadingPromise = pending;
|
|
211
|
+
return pending;
|
|
212
|
+
}
|
|
213
|
+
events.push('bootstrap');
|
|
214
|
+
expect(events).toContain('auth:second');
|
|
215
|
+
return Promise.resolve();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const Root = app.getRootComponent();
|
|
219
|
+
render(<Root />);
|
|
220
|
+
|
|
221
|
+
await waitFor(() => {
|
|
222
|
+
expect(app.router.router.state.location.pathname).toBe('/v2/signin');
|
|
223
|
+
expect(app.router.router.state.location.search).toBe('?redirect=%2Fv2%2Fsecure');
|
|
224
|
+
});
|
|
225
|
+
expect(await screen.findByText('signin page')).toBeInTheDocument();
|
|
226
|
+
expect(screen.queryByTestId('app-spin')).not.toBeInTheDocument();
|
|
227
|
+
expect(ensureLoaded).not.toHaveBeenCalled();
|
|
228
|
+
expect(app.dataSourceManager.loadingPromise).toBeNull();
|
|
229
|
+
expect(events).toEqual(['auth:first']);
|
|
230
|
+
|
|
231
|
+
act(() => {
|
|
232
|
+
app.apiClient.auth.setToken('test-token');
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await act(async () => {
|
|
236
|
+
await app.router.router.navigate('/secure');
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
expect(await screen.findByText('secure page')).toBeInTheDocument();
|
|
240
|
+
await waitFor(() => {
|
|
241
|
+
expect(document.querySelector('.ant-spin-spinning')).not.toBeInTheDocument();
|
|
242
|
+
});
|
|
243
|
+
expect(ensureLoaded).toHaveBeenCalledTimes(1);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should redirect on auth-required /auth:check 401 without bootstrapping data sources', async () => {
|
|
247
|
+
const app = createMockClient({
|
|
248
|
+
publicPath: '/v2/',
|
|
249
|
+
plugins: [NocoBaseBuildInPlugin as any, DummySigninRoutePlugin as any, AuthBootstrapRoutePlugin as any],
|
|
250
|
+
components: { AppSpin: TestingAppSpin },
|
|
251
|
+
router: { type: 'memory', initialEntries: ['/v2/secure'] },
|
|
252
|
+
});
|
|
253
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
254
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
255
|
+
});
|
|
256
|
+
app.apiMock.onGet('/auth:check').reply(401, { errors: [{ code: 'EMPTY_TOKEN' }] });
|
|
257
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockImplementation(() => {
|
|
258
|
+
const pending = new Promise<void>(() => undefined);
|
|
259
|
+
app.dataSourceManager.loadingPromise = pending;
|
|
260
|
+
return pending;
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const Root = app.getRootComponent();
|
|
264
|
+
render(<Root />);
|
|
265
|
+
|
|
266
|
+
await waitFor(() => {
|
|
267
|
+
expect(app.router.router.state.location.pathname).toBe('/v2/signin');
|
|
268
|
+
expect(app.router.router.state.location.search).toBe('?redirect=%2Fv2%2Fsecure');
|
|
269
|
+
});
|
|
270
|
+
expect(await screen.findByText('signin page')).toBeInTheDocument();
|
|
271
|
+
expect(screen.queryByTestId('app-spin')).not.toBeInTheDocument();
|
|
272
|
+
expect(ensureLoaded).not.toHaveBeenCalled();
|
|
273
|
+
expect(app.dataSourceManager.loadingPromise).toBeNull();
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('should surface non-auth /auth:check errors instead of leaving auth-required route spinning', async () => {
|
|
277
|
+
const app = createMockClient({
|
|
278
|
+
publicPath: '/v2/',
|
|
279
|
+
plugins: [NocoBaseBuildInPlugin as any, AuthBootstrapRoutePlugin as any],
|
|
280
|
+
components: { AppSpin: TestingAppSpin, AppError: TestingAppError },
|
|
281
|
+
router: { type: 'memory', initialEntries: ['/v2/secure'] },
|
|
282
|
+
});
|
|
283
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
284
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
285
|
+
});
|
|
286
|
+
app.apiMock.onGet('/auth:check').reply(500, { errors: [{ message: 'auth check failed' }] });
|
|
287
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockResolvedValue(undefined);
|
|
288
|
+
|
|
289
|
+
const Root = app.getRootComponent();
|
|
290
|
+
render(<Root />);
|
|
291
|
+
|
|
292
|
+
expect(await screen.findByRole('alert')).toHaveTextContent('Request failed with status code 500');
|
|
293
|
+
expect(screen.queryByTestId('app-spin')).not.toBeInTheDocument();
|
|
294
|
+
expect(ensureLoaded).not.toHaveBeenCalled();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
it.each(['/v2/signin', '/v2/public'])('should not bootstrap data sources on skipped auth route: %s', async (path) => {
|
|
298
|
+
const app = createMockClient({
|
|
299
|
+
publicPath: '/v2/',
|
|
300
|
+
plugins: [NocoBaseBuildInPlugin as any, DummySigninRoutePlugin as any, SkippedPublicRoutePlugin as any],
|
|
301
|
+
components: { AppSpin: TestingAppSpin },
|
|
302
|
+
router: { type: 'memory', initialEntries: [path] },
|
|
303
|
+
});
|
|
304
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
305
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
306
|
+
});
|
|
307
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockResolvedValue(undefined);
|
|
308
|
+
|
|
309
|
+
const Root = app.getRootComponent();
|
|
310
|
+
render(<Root />);
|
|
311
|
+
|
|
312
|
+
expect(await screen.findByText(path === '/v2/signin' ? 'signin page' : 'public page')).toBeInTheDocument();
|
|
313
|
+
expect(screen.queryByTestId('app-spin')).not.toBeInTheDocument();
|
|
314
|
+
expect(ensureLoaded).not.toHaveBeenCalled();
|
|
315
|
+
expect(app.apiMock.history.get.filter((request) => request.url === '/auth:check')).toHaveLength(0);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('should bootstrap data sources for authenticated auth-required route access', async () => {
|
|
319
|
+
const app = createMockClient({
|
|
320
|
+
publicPath: '/v2/',
|
|
321
|
+
plugins: [NocoBaseBuildInPlugin as any, AuthBootstrapRoutePlugin as any],
|
|
322
|
+
router: { type: 'memory', initialEntries: ['/v2/secure'] },
|
|
323
|
+
});
|
|
324
|
+
app.apiClient.auth.setToken('test-token');
|
|
325
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
326
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
327
|
+
});
|
|
328
|
+
app.apiMock.onGet('/auth:check').reply(200, { data: { id: 1 } });
|
|
329
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockResolvedValue(undefined);
|
|
330
|
+
|
|
331
|
+
const Root = app.getRootComponent();
|
|
332
|
+
render(<Root />);
|
|
333
|
+
|
|
334
|
+
expect(await screen.findByText('secure page')).toBeInTheDocument();
|
|
335
|
+
expect(ensureLoaded).toHaveBeenCalledTimes(1);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
it('should not auth-check or bootstrap authCheck false routes', async () => {
|
|
339
|
+
const app = createMockClient({
|
|
340
|
+
publicPath: '/v2/',
|
|
341
|
+
plugins: [NocoBaseBuildInPlugin as any, AuthBootstrapRoutePlugin as any],
|
|
342
|
+
router: { type: 'memory', initialEntries: ['/v2/guest'] },
|
|
343
|
+
});
|
|
344
|
+
app.apiMock.onGet('app:getLang').reply(200, {
|
|
345
|
+
data: { lang: 'en-US', resources: { client: {} }, cron: {} },
|
|
346
|
+
});
|
|
347
|
+
const ensureLoaded = vi.spyOn(app.dataSourceManager, 'ensureLoaded').mockResolvedValue(undefined);
|
|
348
|
+
|
|
349
|
+
const Root = app.getRootComponent();
|
|
350
|
+
render(<Root />);
|
|
351
|
+
|
|
352
|
+
expect(await screen.findByText('guest page')).toBeInTheDocument();
|
|
353
|
+
expect(ensureLoaded).not.toHaveBeenCalled();
|
|
354
|
+
expect(app.apiMock.history.get.filter((request) => request.url === '/auth:check')).toHaveLength(0);
|
|
355
|
+
});
|
|
356
|
+
|
|
158
357
|
it('should render v2 admin root without redirecting away', async () => {
|
|
159
358
|
const app = createMockClient({
|
|
160
359
|
publicPath: '/v2/',
|
|
@@ -28,6 +28,13 @@ export type CurrentUserState = {
|
|
|
28
28
|
loading: boolean;
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
type CurrentUserAuthStatus = 'unknown' | 'authenticated' | 'unauthenticated' | 'redirecting';
|
|
32
|
+
|
|
33
|
+
type CurrentUserInternalState = CurrentUserState & {
|
|
34
|
+
authStatus: CurrentUserAuthStatus;
|
|
35
|
+
error?: Error | null;
|
|
36
|
+
};
|
|
37
|
+
|
|
31
38
|
export type CurrentRoleOption = {
|
|
32
39
|
name: string;
|
|
33
40
|
title: string;
|
|
@@ -151,7 +158,7 @@ const DataSourceBootstrapProvider: FC = ({ children }) => {
|
|
|
151
158
|
}
|
|
152
159
|
};
|
|
153
160
|
|
|
154
|
-
|
|
161
|
+
run();
|
|
155
162
|
|
|
156
163
|
return () => {
|
|
157
164
|
mounted = false;
|
|
@@ -173,21 +180,33 @@ const CurrentUserProvider: FC = ({ children }) => {
|
|
|
173
180
|
const app = useApp<Application>();
|
|
174
181
|
const location = useLocation();
|
|
175
182
|
const navigate = useNavigate();
|
|
176
|
-
const [state, setState] = useState<
|
|
183
|
+
const [state, setState] = useState<CurrentUserInternalState>({ loading: true, authStatus: 'unknown' });
|
|
177
184
|
const locationRef = useRef(location);
|
|
178
185
|
locationRef.current = location;
|
|
179
186
|
const authCheckRouteState = getCurrentUserAuthCheckRouteState(app, location.pathname);
|
|
187
|
+
const shouldBlockAuthRequiredRoute = authCheckRouteState === 'required' && state.authStatus !== 'authenticated';
|
|
188
|
+
const contextValue = useMemo<CurrentUserState>(
|
|
189
|
+
() => ({
|
|
190
|
+
data: state.data,
|
|
191
|
+
loading: state.loading,
|
|
192
|
+
}),
|
|
193
|
+
[state.data, state.loading],
|
|
194
|
+
);
|
|
180
195
|
|
|
181
196
|
useEffect(() => {
|
|
182
197
|
let mounted = true;
|
|
183
198
|
|
|
184
199
|
if (authCheckRouteState !== 'required') {
|
|
185
200
|
// 认证页等免鉴权路由不应再执行 `/auth:check`,否则未登录时会重复鉴权并触发重定向抖动。
|
|
186
|
-
setState({ loading: false });
|
|
201
|
+
setState({ loading: false, authStatus: 'unauthenticated', error: null });
|
|
187
202
|
return;
|
|
188
203
|
}
|
|
189
204
|
|
|
190
|
-
setState((previous) =>
|
|
205
|
+
setState((previous) =>
|
|
206
|
+
previous.authStatus === 'authenticated'
|
|
207
|
+
? previous
|
|
208
|
+
: { data: previous.data, loading: true, authStatus: 'unknown', error: null },
|
|
209
|
+
);
|
|
191
210
|
|
|
192
211
|
const run = async () => {
|
|
193
212
|
try {
|
|
@@ -204,11 +223,12 @@ const CurrentUserProvider: FC = ({ children }) => {
|
|
|
204
223
|
const user = res?.data?.data;
|
|
205
224
|
// 服务端通过 `{ code: 302, redirect }` 通知客户端先去某个中间页(例如 2FA 验证页)。这类响应没有 user.id,但也不能视为未登录——否则会和处理 302 的全局响应拦截器 (例如 plugin-two-factor-authentication 注册的那一个)竞态,而 `window.location.replace` 会覆盖更早发出的 `window.location.href`,把用户错误地弹回登录页。让响应拦截器接管跳转。
|
|
206
225
|
if (user?.code === 302) {
|
|
207
|
-
setState({ loading: false });
|
|
226
|
+
setState({ loading: false, authStatus: 'redirecting', error: null });
|
|
208
227
|
return;
|
|
209
228
|
}
|
|
210
229
|
if (user?.id == null) {
|
|
211
230
|
// 用 react-router navigate (虚拟跳转)而不是 location.replace, 这样如果有其他响应拦截器已经发起了 window.location.href 整页跳转(例如 2FA 插件接收到服务端 302 重定向), 真实跳转可以胜出 navigate, 不会被这里的 signin 重定向覆盖。
|
|
231
|
+
setState({ loading: true, authStatus: 'unauthenticated', error: null });
|
|
212
232
|
navigate(`/signin?redirect=${encodeURIComponent(getCurrentV2RedirectPath(app, locationRef.current))}`, {
|
|
213
233
|
replace: true,
|
|
214
234
|
});
|
|
@@ -230,21 +250,28 @@ const CurrentUserProvider: FC = ({ children }) => {
|
|
|
230
250
|
setState({
|
|
231
251
|
data: res?.data,
|
|
232
252
|
loading: false,
|
|
253
|
+
authStatus: 'authenticated',
|
|
254
|
+
error: null,
|
|
233
255
|
});
|
|
234
|
-
} catch (error:
|
|
256
|
+
} catch (error: unknown) {
|
|
235
257
|
if (!mounted) {
|
|
236
258
|
return;
|
|
237
259
|
}
|
|
238
260
|
|
|
239
|
-
const
|
|
261
|
+
const errorLike = error as { response?: { status?: number }; status?: number };
|
|
262
|
+
const isAuthError = errorLike?.response?.status === 401 || errorLike?.status === 401;
|
|
240
263
|
if (isAuthError) {
|
|
264
|
+
setState({ loading: true, authStatus: 'unauthenticated', error: null });
|
|
241
265
|
navigate(`/signin?redirect=${encodeURIComponent(getCurrentV2RedirectPath(app, locationRef.current))}`, {
|
|
242
266
|
replace: true,
|
|
243
267
|
});
|
|
244
268
|
return;
|
|
245
269
|
}
|
|
246
|
-
setState({
|
|
247
|
-
|
|
270
|
+
setState({
|
|
271
|
+
loading: false,
|
|
272
|
+
authStatus: 'unknown',
|
|
273
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
274
|
+
});
|
|
248
275
|
}
|
|
249
276
|
};
|
|
250
277
|
|
|
@@ -255,11 +282,15 @@ const CurrentUserProvider: FC = ({ children }) => {
|
|
|
255
282
|
};
|
|
256
283
|
}, [app, authCheckRouteState, navigate]);
|
|
257
284
|
|
|
258
|
-
if (state.
|
|
285
|
+
if (state.error) {
|
|
286
|
+
throw state.error;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (state.loading || shouldBlockAuthRequiredRoute) {
|
|
259
290
|
return app.renderComponent('AppSpin');
|
|
260
291
|
}
|
|
261
292
|
|
|
262
|
-
return <CurrentUserContext.Provider value={
|
|
293
|
+
return <CurrentUserContext.Provider value={contextValue}>{children}</CurrentUserContext.Provider>;
|
|
263
294
|
};
|
|
264
295
|
|
|
265
296
|
const RootRedirect: FC = () => {
|
|
@@ -289,8 +320,9 @@ export class NocoBaseBuildInPlugin extends Plugin<any, Application> {
|
|
|
289
320
|
this.addComponents();
|
|
290
321
|
this.addRoutes();
|
|
291
322
|
|
|
292
|
-
|
|
323
|
+
// Auth-required routes must finish auth check or redirect before data source metadata requests can start.
|
|
293
324
|
this.app.use(CurrentUserProvider);
|
|
325
|
+
this.app.use(DataSourceBootstrapProvider);
|
|
294
326
|
this.app.flowEngine.registerModels({
|
|
295
327
|
AdminLayoutModel,
|
|
296
328
|
AdminLayoutMenuItemModel,
|