@tachybase/module-backup 1.0.6 → 1.0.18

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.
@@ -1 +1 @@
1
- (function(p,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("@tachybase/client"),require("react/jsx-runtime"),require("react"),require("@tachybase/components"),require("@ant-design/icons"),require("antd"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","react/jsx-runtime","react","@tachybase/components","@ant-design/icons","antd","react-i18next"],r):(p=typeof globalThis!="undefined"?globalThis:p||self,r(p["@tachybase/module-backup"]={},p["@tachybase/client"],p.jsxRuntime,p.react,p["@tachybase/components"],p["@ant-design/icons"],p.antd,p["react-i18next"]))})(this,function(p,r,e,y,L,x,l,P){"use strict";var Z=Object.defineProperty,R=Object.defineProperties;var ee=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var te=Object.prototype.hasOwnProperty,oe=Object.prototype.propertyIsEnumerable;var W=(p,r,e)=>r in p?Z(p,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):p[r]=e,q=(p,r)=>{for(var e in r||(r={}))te.call(r,e)&&W(p,e,r[e]);if($)for(var e of $(r))oe.call(r,e)&&W(p,e,r[e]);return p},E=(p,r)=>R(p,ee(r));var T=(p,r,e)=>new Promise((y,L)=>{var x=m=>{try{P(e.next(m))}catch(A){L(A)}},l=m=>{try{P(e.throw(m))}catch(A){L(A)}},P=m=>m.done?y(m.value):Promise.resolve(m.value).then(x,l);P((e=e.apply(p,r)).next())});var m=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},A={exports:{}};(function(a,g){(function(i,c){c()})(m,function(){function i(t,s){return typeof s=="undefined"?s={autoBom:!1}:typeof s!="object"&&(console.warn("Deprecated: Expected third argument to be a object"),s={autoBom:!s}),s.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(t.type)?new Blob(["\uFEFF",t],{type:t.type}):t}function c(t,s,k){var n=new XMLHttpRequest;n.open("GET",t),n.responseType="blob",n.onload=function(){v(n.response,s,k)},n.onerror=function(){console.error("could not download file")},n.send()}function u(t){var s=new XMLHttpRequest;s.open("HEAD",t,!1);try{s.send()}catch(k){}return 200<=s.status&&299>=s.status}function h(t){try{t.dispatchEvent(new MouseEvent("click"))}catch(k){var s=document.createEvent("MouseEvents");s.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),t.dispatchEvent(s)}}var f=typeof window=="object"&&window.window===window?window:typeof self=="object"&&self.self===self?self:typeof m=="object"&&m.global===m?m:void 0,w=f.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),v=f.saveAs||(typeof window!="object"||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!w?function(t,s,k){var n=f.URL||f.webkitURL,d=document.createElement("a");s=s||t.name||"download",d.download=s,d.rel="noopener",typeof t=="string"?(d.href=t,d.origin===location.origin?h(d):u(d.href)?c(t,s,k):h(d,d.target="_blank")):(d.href=n.createObjectURL(t),setTimeout(function(){n.revokeObjectURL(d.href)},4e4),setTimeout(function(){h(d)},0))}:"msSaveOrOpenBlob"in navigator?function(t,s,k){if(s=s||t.name||"download",typeof t!="string")navigator.msSaveOrOpenBlob(i(t,k),s);else if(u(t))c(t,s,k);else{var n=document.createElement("a");n.href=t,n.target="_blank",setTimeout(function(){h(n)})}}:function(t,s,k,n){if(n=n||open("","_blank"),n&&(n.document.title=n.document.body.innerText="downloading..."),typeof t=="string")return c(t,s,k);var d=t.type==="application/octet-stream",C=/constructor/i.test(f.HTMLElement)||f.safari,o=/CriOS\/[\d]+/.test(navigator.userAgent);if((o||d&&C||w)&&typeof FileReader!="undefined"){var b=new FileReader;b.onloadend=function(){var S=b.result;S=o?S:S.replace(/^data:[^;]*;/,"data:attachment/file;"),n?n.location.href=S:location=S,n=null},b.readAsDataURL(t)}else{var B=f.URL||f.webkitURL,O=B.createObjectURL(t);n?n.location=O:location.href=O,n=null,setTimeout(function(){B.revokeObjectURL(O)},4e4)}});f.saveAs=v.saveAs=v,a.exports=v})})(A);var K=A.exports;const I="backup";function F(){return P.useTranslation(I,{nsMode:"fallback"})}const{Dragger:X}=l.Upload;function J(a){const g=c=>{var u;(u=a.onChange)==null||u.call(a,c)},i=r.useAPIClient();return E(q({},a),{customRequest({action:c,data:u,file:h,filename:f,headers:w,onError:v,onProgress:t,onSuccess:s,withCredentials:k}){const n=new FormData;return u&&Object.keys(u).forEach(d=>{n.append(d,u[d])}),n.append(f,h),i.axios.post(c,n,{withCredentials:k,headers:w,onUploadProgress:({total:d,loaded:C})=>{t({percent:Math.round(C/d*100).toFixed(2)},h)}}).then(({data:d})=>{s(d,h)}).catch(v).finally(()=>{}),{abort(){console.log("upload progress is aborted.")}}},onChange:g})}const U=a=>{const{collectionsData:g}=a,{t:i}=F(),[c,u]=y.useState(!1),[h,f]=y.useState(g);y.useEffect(()=>{f(g)},[g]);const w=r.useAPIClient(),v=r.useCompile(),t=y.useMemo(()=>w.resource("backupFiles"),[w]),s=()=>T(this,null,function*(){if(a.isBackup){const o=yield t.dumpableCollections();f(o==null?void 0:o.data),u(!0)}u(!0)}),k=()=>{u(!1)},n=()=>{u(!1)},d=[{title:i("Collection"),dataIndex:"collection",key:"collection",render:(o,b)=>{const B=v(b.title);return b.name===B?B:e.jsxs("div",{children:[b.name," ",e.jsxs("span",{style:{color:"rgba(0, 0, 0, 0.3)",fontSize:"0.9em"},children:["(",v(b.title),")"]})]})}},{title:i("Origin"),dataIndex:"origin",key:"origin",width:"50%"}],C=Object.keys(h||{}).map(o=>({key:o,label:i(`${o}.title`),children:e.jsxs(e.Fragment,{children:[e.jsx(l.Alert,{style:{marginBottom:16},message:i(`${o}.description`)}),e.jsx(l.Table,{pagination:{pageSize:100},bordered:!0,size:"small",dataSource:h[o],columns:d,scroll:{y:400}})]})}));return e.jsxs(e.Fragment,{children:[e.jsx("a",{onClick:s,children:i("Learn more")}),e.jsx(l.Modal,{title:i("Backup instructions"),width:"80vw",open:c,footer:null,onOk:k,onCancel:n,children:e.jsx(l.Tabs,{defaultActiveKey:"required",items:C})})]})},G=({ButtonComponent:a=l.Button,title:g,upload:i=!1,fileData:c})=>{const{t:u}=F(),[h,f]=y.useState(["required"]),[w,v]=y.useState(!1),[t,s]=y.useState(null),[k,n]=y.useState(!1),d=r.useAPIClient(),C=y.useMemo(()=>d.resource("backupFiles"),[d]),[o,b]=y.useState([]);y.useEffect(()=>{b(Object.keys((t==null?void 0:t.dumpableCollectionsGroupByGroup)||[]).map(M=>({value:M,label:u(`${M}.title`),disabled:["required","skipped"].includes(M)})))},[t]);const B=()=>T(this,null,function*(){var M,z,H;if(v(!0),!i){n(!0);const{data:D}=yield C.get({filterByTk:c.name});b(Object.keys(((z=(M=D==null?void 0:D.data)==null?void 0:M.meta)==null?void 0:z.dumpableCollectionsGroupByGroup)||[]).map(j=>({value:j,label:u(`${j}.title`),disabled:["required","skipped"].includes(j)}))),s((H=D==null?void 0:D.data)==null?void 0:H.meta),n(!1)}}),O=()=>{C.restore({values:{dataTypes:h,filterByTk:c==null?void 0:c.name,key:t==null?void 0:t.key}}),v(!1)},S=()=>{v(!1),s(null),f(["required"])};return e.jsxs(e.Fragment,{children:[e.jsx(a,{onClick:B,children:g}),e.jsx(l.Modal,{title:u("Restore"),width:800,footer:i&&!t?null:void 0,open:w,onOk:O,onCancel:S,children:e.jsxs(l.Spin,{spinning:k,children:[i&&!t&&e.jsx(V,{setRestoreData:s}),(!i||t)&&[e.jsxs("strong",{style:{fontWeight:600,display:"block",margin:"16px 0 8px"},children:[u("Select the data to be restored")," (",e.jsx(U,{collectionsData:t==null?void 0:t.dumpableCollectionsGroupByGroup}),"):"]},"info"),e.jsx("div",{style:{lineHeight:2,marginBottom:8},children:e.jsx(L.FormItem,{children:e.jsx(r.Checkbox.Group,{options:o,style:{flexDirection:"column"},value:h,onChange:M=>f(M)})})},"dataType")]]})})]})},Q=({ButtonComponent:a=l.Button,refresh:g})=>{const{t:i}=F(),[c,u]=y.useState(!1),[h,f]=y.useState(["required"]),w=r.useAPIClient(),{notification:v}=l.App.useApp(),[t,s]=y.useState([]),k=()=>T(this,null,function*(){const{data:C}=yield w.resource("backupFiles").dumpableCollections();s(Object.keys(C||[]).map(o=>({value:o,label:i(`${o}.title`),disabled:["required","skipped"].includes(o)}))),u(!0)}),n=C=>{w.request({url:"backupFiles:create",method:"post",data:{dataTypes:h,method:C}}).finally(()=>{v.destroy("backup")}),v.info({key:"backup",message:e.jsxs("span",{children:[i("Processing..."),"    ",e.jsx(l.Spin,{indicator:e.jsx(x.LoadingOutlined,{style:{fontSize:24},spin:!0})})]}),duration:0}),u(!1),f(["required"]),setTimeout(()=>{g()},500)},d=()=>{u(!1),f(["required"])};return e.jsxs(e.Fragment,{children:[e.jsx(a,{icon:e.jsx(x.PlusOutlined,{}),type:"primary",onClick:k,children:i("New backup")}),e.jsxs(l.Modal,{title:i("New backup"),width:800,open:c,onCancel:d,footer:[e.jsxs(l.Row,{gutter:16,justify:"end",align:"middle",children:[e.jsx(l.Col,{children:e.jsx(l.Button,{onClick:d,children:i("Cancel")},"cancel")}),e.jsx(l.Col,{children:e.jsx(l.Dropdown.Button,{type:"primary",onClick:()=>n("priority"),overlay:e.jsxs(l.Menu,{children:[e.jsx(l.Menu.Item,{onClick:()=>n("main"),children:i("Self backup")},"main"),e.jsx(l.Menu.Item,{onClick:()=>n("worker"),children:i("Worker backup")},"worker")]}),children:i("Backup")},"submit")})]})],children:[e.jsxs("strong",{style:{fontWeight:600,display:"block",margin:"16px 0 8px"},children:[i("Select the data to be backed up")," (",e.jsx(U,{isBackup:!0}),"):"]}),e.jsx("div",{style:{lineHeight:2,marginBottom:8},children:e.jsx(r.Checkbox.Group,{options:t,style:{flexDirection:"column"},onChange:C=>f(C),value:h})})]})]})},V=a=>{const{t:g}=F(),i={multiple:!1,action:"/backupFiles:upload",onChange(c){var h,f,w;c.fileList.length>1&&c.fileList.splice(0,c.fileList.length-1);const{status:u}=c.file;u==="done"?(l.message.success(`${c.file.name} `+g("file uploaded successfully")),a.setRestoreData(E(q({},(f=(h=c.file.response)==null?void 0:h.data)==null?void 0:f.meta),{key:(w=c.file.response)==null?void 0:w.data.key}))):u==="error"&&l.message.error(`${c.file.name} `+g("file upload failed"))},onDrop(c){console.log("Dropped files",c.dataTransfer.files)}};return e.jsxs(X,E(q({},J(i)),{children:[e.jsx("p",{className:"ant-upload-drag-icon",children:e.jsx(x.InboxOutlined,{})}),e.jsxs("p",{className:"ant-upload-text",children:[" ",g("Click or drag file to this area to upload")]})]}))},Y=()=>{const{t:a}=F(),g=r.useAPIClient(),[i,c]=y.useState([]),[u,h]=y.useState(!1),[f,w]=y.useState(!1),{modal:v,notification:t}=l.App.useApp(),s=y.useMemo(()=>g.resource("backupFiles"),[g]),k=y.useCallback(()=>T(this,null,function*(){yield n()}),[]);r.useNoticeSub("backup",o=>{(t[o.level]||t.info)({key:"backup",message:o.msg}),k()}),y.useEffect(()=>{n()},[]);const n=()=>T(this,null,function*(){h(!0);const{data:o}=yield s.list();c(o.data),h(!1)}),d=o=>T(this,null,function*(){w(o.name);const b=yield g.request({url:"backupFiles:download",method:"get",params:{filterByTk:o.name},responseType:"blob",onDownloadProgress:O=>{const S=Math.round(O.loaded*100/O.total);S>=100?t.success({key:"downloadBackup",message:e.jsx("span",{children:a("Downloaded success!")}),duration:1}):t.info({key:"downloadBackup",message:e.jsxs("span",{children:[a("Downloading ")+S+"%","    ",e.jsx(l.Spin,{indicator:e.jsx(x.LoadingOutlined,{style:{fontSize:24},spin:!0})})]}),duration:0})}});w(!1);const B=new Blob([b.data]);K.saveAs(B,o.name)}),C=o=>{v.confirm({title:a("Delete record",{ns:"core"}),content:a("Are you sure you want to delete it?",{ns:"core"}),onOk:()=>T(this,null,function*(){yield s.destroy({filterByTk:o.name}),yield n(),l.message.success(a("Deleted successfully"))})})};return e.jsx("div",{children:e.jsxs(l.Card,{bordered:!1,children:[e.jsxs(l.Space,{style:{float:"right",marginBottom:16},children:[e.jsx(l.Button,{onClick:k,icon:e.jsx(x.ReloadOutlined,{}),children:a("Refresh")}),e.jsx(G,{upload:!0,title:e.jsxs(e.Fragment,{children:[e.jsx(x.UploadOutlined,{})," ",a("Restore backup from local")]})}),e.jsx(Q,{refresh:k})]}),e.jsx(l.Table,{dataSource:i,loading:u,columns:[{title:a("Backup file"),dataIndex:"name",width:400,onCell:o=>o.inProgress?{colSpan:4}:{},render:(o,b)=>b.inProgress?e.jsxs("div",{style:{color:"rgba(0, 0, 0, 0.88)"},children:[o,"(",a("Backing up"),"...)"]}):e.jsx("div",{children:o})},{title:a("File size"),dataIndex:"fileSize",onCell:o=>o.inProgress?{colSpan:0}:{}},{title:a("Created at",{ns:"core"}),dataIndex:"createdAt",onCell:o=>o.inProgress?{colSpan:0}:{},render:o=>e.jsx(r.DatePicker.ReadPretty,{value:o,showTime:!0})},{title:a("Actions",{ns:"core"}),dataIndex:"actions",onCell:o=>o.inProgress?{colSpan:0}:{},render:(o,b)=>e.jsxs(l.Space,{split:e.jsx(l.Divider,{type:"vertical"}),children:[e.jsx(G,{ButtonComponent:"a",title:a("Restore"),fileData:b}),e.jsx("a",{type:"link",onClick:()=>d(b),children:a("Download")}),e.jsx("a",{onClick:()=>C(b),children:a("Delete")})]})}]})]})})},_=function(a){return e.jsx(r.SchemaComponentOptions,{children:a.children})};_.displayName="DuplicatorProvider";class N extends r.Plugin{load(){return T(this,null,function*(){this.app.use(_),this.app.systemSettingsManager.add("system-services."+I,{title:this.t("Backup & Restore"),icon:"CloudServerOutlined",Component:Y,aclSnippet:"pm.backup.restore"})})}}p.PluginBackupRestoreClient=N,p.default=N,Object.defineProperties(p,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(p,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("@tachybase/client"),require("react/jsx-runtime"),require("react"),require("@tachybase/components"),require("@ant-design/icons"),require("antd"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","react/jsx-runtime","react","@tachybase/components","@ant-design/icons","antd","react-i18next"],r):(p=typeof globalThis!="undefined"?globalThis:p||self,r(p["@tachybase/module-backup"]={},p["@tachybase/client"],p.jsxRuntime,p.react,p["@tachybase/components"],p["@ant-design/icons"],p.antd,p["react-i18next"]))})(this,function(p,r,e,k,L,x,l,P){"use strict";var Z=Object.defineProperty,R=Object.defineProperties;var ee=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var te=Object.prototype.hasOwnProperty,oe=Object.prototype.propertyIsEnumerable;var W=(p,r,e)=>r in p?Z(p,r,{enumerable:!0,configurable:!0,writable:!0,value:e}):p[r]=e,E=(p,r)=>{for(var e in r||(r={}))te.call(r,e)&&W(p,e,r[e]);if($)for(var e of $(r))oe.call(r,e)&&W(p,e,r[e]);return p},q=(p,r)=>R(p,ee(r));var T=(p,r,e)=>new Promise((k,L)=>{var x=m=>{try{P(e.next(m))}catch(A){L(A)}},l=m=>{try{P(e.throw(m))}catch(A){L(A)}},P=m=>m.done?k(m.value):Promise.resolve(m.value).then(x,l);P((e=e.apply(p,r)).next())});var m=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},A={exports:{}};(function(a,b){(function(i,c){c()})(m,function(){function i(t,s){return typeof s=="undefined"?s={autoBom:!1}:typeof s!="object"&&(console.warn("Deprecated: Expected third argument to be a object"),s={autoBom:!s}),s.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(t.type)?new Blob(["\uFEFF",t],{type:t.type}):t}function c(t,s,g){var n=new XMLHttpRequest;n.open("GET",t),n.responseType="blob",n.onload=function(){v(n.response,s,g)},n.onerror=function(){console.error("could not download file")},n.send()}function u(t){var s=new XMLHttpRequest;s.open("HEAD",t,!1);try{s.send()}catch(g){}return 200<=s.status&&299>=s.status}function h(t){try{t.dispatchEvent(new MouseEvent("click"))}catch(g){var s=document.createEvent("MouseEvents");s.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),t.dispatchEvent(s)}}var f=typeof window=="object"&&window.window===window?window:typeof self=="object"&&self.self===self?self:typeof m=="object"&&m.global===m?m:void 0,w=f.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),v=f.saveAs||(typeof window!="object"||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!w?function(t,s,g){var n=f.URL||f.webkitURL,d=document.createElement("a");s=s||t.name||"download",d.download=s,d.rel="noopener",typeof t=="string"?(d.href=t,d.origin===location.origin?h(d):u(d.href)?c(t,s,g):h(d,d.target="_blank")):(d.href=n.createObjectURL(t),setTimeout(function(){n.revokeObjectURL(d.href)},4e4),setTimeout(function(){h(d)},0))}:"msSaveOrOpenBlob"in navigator?function(t,s,g){if(s=s||t.name||"download",typeof t!="string")navigator.msSaveOrOpenBlob(i(t,g),s);else if(u(t))c(t,s,g);else{var n=document.createElement("a");n.href=t,n.target="_blank",setTimeout(function(){h(n)})}}:function(t,s,g,n){if(n=n||open("","_blank"),n&&(n.document.title=n.document.body.innerText="downloading..."),typeof t=="string")return c(t,s,g);var d=t.type==="application/octet-stream",C=/constructor/i.test(f.HTMLElement)||f.safari,o=/CriOS\/[\d]+/.test(navigator.userAgent);if((o||d&&C||w)&&typeof FileReader!="undefined"){var y=new FileReader;y.onloadend=function(){var S=y.result;S=o?S:S.replace(/^data:[^;]*;/,"data:attachment/file;"),n?n.location.href=S:location=S,n=null},y.readAsDataURL(t)}else{var B=f.URL||f.webkitURL,O=B.createObjectURL(t);n?n.location=O:location.href=O,n=null,setTimeout(function(){B.revokeObjectURL(O)},4e4)}});f.saveAs=v.saveAs=v,a.exports=v})})(A);var K=A.exports;const I="backup";function F(){return P.useTranslation(I,{nsMode:"fallback"})}const{Dragger:X}=l.Upload;function J(a){const b=c=>{var u;(u=a.onChange)==null||u.call(a,c)},i=r.useAPIClient();return q(E({},a),{customRequest({action:c,data:u,file:h,filename:f,headers:w,onError:v,onProgress:t,onSuccess:s,withCredentials:g}){const n=new FormData;return u&&Object.keys(u).forEach(d=>{n.append(d,u[d])}),n.append(f,h),i.axios.post(c,n,{withCredentials:g,headers:w,onUploadProgress:({total:d,loaded:C})=>{t({percent:Math.round(C/d*100).toFixed(2)},h)}}).then(({data:d})=>{s(d,h)}).catch(v).finally(()=>{}),{abort(){console.log("upload progress is aborted.")}}},onChange:b})}const U=a=>{const{collectionsData:b}=a,{t:i}=F(),[c,u]=k.useState(!1),[h,f]=k.useState(b);k.useEffect(()=>{f(b)},[b]);const w=r.useAPIClient(),v=r.useCompile(),t=k.useMemo(()=>w.resource("backupFiles"),[w]),s=()=>T(this,null,function*(){if(a.isBackup){const o=yield t.dumpableCollections();f(o==null?void 0:o.data),u(!0)}u(!0)}),g=()=>{u(!1)},n=()=>{u(!1)},d=[{title:i("Collection"),dataIndex:"collection",key:"collection",render:(o,y)=>{const B=v(y.title);return y.name===B?B:e.jsxs("div",{children:[y.name," ",e.jsxs("span",{style:{color:"rgba(0, 0, 0, 0.3)",fontSize:"0.9em"},children:["(",v(y.title),")"]})]})}},{title:i("Origin"),dataIndex:"origin",key:"origin",width:"50%"}],C=Object.keys(h||{}).map(o=>({key:o,label:i(`${o}.title`),children:e.jsxs(e.Fragment,{children:[e.jsx(l.Alert,{style:{marginBottom:16},message:i(`${o}.description`)}),e.jsx(l.Table,{pagination:{pageSize:100},bordered:!0,size:"small",dataSource:h[o],columns:d,scroll:{y:400}})]})}));return e.jsxs(e.Fragment,{children:[e.jsx("a",{onClick:s,children:i("Learn more")}),e.jsx(l.Modal,{title:i("Backup instructions"),width:"80vw",open:c,footer:null,onOk:g,onCancel:n,children:e.jsx(l.Tabs,{defaultActiveKey:"required",items:C})})]})},G=({ButtonComponent:a=l.Button,title:b,upload:i=!1,fileData:c})=>{const{t:u}=F(),[h,f]=k.useState(["required"]),[w,v]=k.useState(!1),[t,s]=k.useState(null),[g,n]=k.useState(!1),d=r.useAPIClient(),C=k.useMemo(()=>d.resource("backupFiles"),[d]),[o,y]=k.useState([]);k.useEffect(()=>{y(Object.keys((t==null?void 0:t.dumpableCollectionsGroupByGroup)||[]).map(M=>({value:M,label:u(`${M}.title`),disabled:["required","skipped"].includes(M)})))},[t]);const B=()=>T(this,null,function*(){var M,z,H;if(v(!0),!i){n(!0);const{data:D}=yield C.get({filterByTk:c.name});y(Object.keys(((z=(M=D==null?void 0:D.data)==null?void 0:M.meta)==null?void 0:z.dumpableCollectionsGroupByGroup)||[]).map(j=>({value:j,label:u(`${j}.title`),disabled:["required","skipped"].includes(j)}))),s((H=D==null?void 0:D.data)==null?void 0:H.meta),n(!1)}}),O=()=>{C.restore({values:{dataTypes:h,filterByTk:c==null?void 0:c.name,key:t==null?void 0:t.key}}),v(!1)},S=()=>{v(!1),s(null),f(["required"])};return e.jsxs(e.Fragment,{children:[e.jsx(a,{onClick:B,children:b}),e.jsx(l.Modal,{title:u("Restore"),width:800,footer:i&&!t?null:void 0,open:w,onOk:O,onCancel:S,children:e.jsxs(l.Spin,{spinning:g,children:[i&&!t&&e.jsx(V,{setRestoreData:s}),(!i||t)&&[e.jsxs("strong",{style:{fontWeight:600,display:"block",margin:"16px 0 8px"},children:[u("Select the data to be restored")," (",e.jsx(U,{collectionsData:t==null?void 0:t.dumpableCollectionsGroupByGroup}),"):"]},"info"),e.jsx("div",{style:{lineHeight:2,marginBottom:8},children:e.jsx(L.FormItem,{children:e.jsx(r.Checkbox.Group,{options:o,style:{flexDirection:"column"},value:h,onChange:M=>f(M)})})},"dataType")]]})})]})},Q=({ButtonComponent:a=l.Button,refresh:b})=>{const{t:i}=F(),[c,u]=k.useState(!1),[h,f]=k.useState(["required"]),w=r.useAPIClient(),{notification:v}=l.App.useApp(),[t,s]=k.useState([]),g=()=>T(this,null,function*(){const{data:C}=yield w.resource("backupFiles").dumpableCollections();s(Object.keys(C||[]).map(o=>({value:o,label:i(`${o}.title`),disabled:["required","skipped"].includes(o)}))),u(!0)}),n=C=>{w.request({url:"backupFiles:create",method:"post",data:{dataTypes:h,method:C}}),v.info({key:"backup",message:e.jsxs("span",{children:[i("Processing..."),"    ",e.jsx(l.Spin,{indicator:e.jsx(x.LoadingOutlined,{style:{fontSize:24},spin:!0})})]}),duration:0}),u(!1),f(["required"]),setTimeout(()=>{b()},500)},d=()=>{u(!1),f(["required"])};return e.jsxs(e.Fragment,{children:[e.jsx(a,{icon:e.jsx(x.PlusOutlined,{}),type:"primary",onClick:g,children:i("New backup")}),e.jsxs(l.Modal,{title:i("New backup"),width:800,open:c,onCancel:d,footer:[e.jsxs(l.Row,{gutter:16,justify:"end",align:"middle",children:[e.jsx(l.Col,{children:e.jsx(l.Button,{onClick:d,children:i("Cancel")},"cancel")}),e.jsx(l.Col,{children:e.jsx(l.Dropdown.Button,{type:"primary",onClick:()=>n("priority"),overlay:e.jsxs(l.Menu,{children:[e.jsx(l.Menu.Item,{onClick:()=>n("main"),children:i("Self backup")},"main"),e.jsx(l.Menu.Item,{onClick:()=>n("worker"),children:i("Worker backup")},"worker")]}),children:i("Backup")},"submit")})]})],children:[e.jsxs("strong",{style:{fontWeight:600,display:"block",margin:"16px 0 8px"},children:[i("Select the data to be backed up")," (",e.jsx(U,{isBackup:!0}),"):"]}),e.jsx("div",{style:{lineHeight:2,marginBottom:8},children:e.jsx(r.Checkbox.Group,{options:t,style:{flexDirection:"column"},onChange:C=>f(C),value:h})})]})]})},V=a=>{const{t:b}=F(),i={multiple:!1,action:"/backupFiles:upload",onChange(c){var h,f,w;c.fileList.length>1&&c.fileList.splice(0,c.fileList.length-1);const{status:u}=c.file;u==="done"?(l.message.success(`${c.file.name} `+b("file uploaded successfully")),a.setRestoreData(q(E({},(f=(h=c.file.response)==null?void 0:h.data)==null?void 0:f.meta),{key:(w=c.file.response)==null?void 0:w.data.key}))):u==="error"&&l.message.error(`${c.file.name} `+b("file upload failed"))},onDrop(c){console.log("Dropped files",c.dataTransfer.files)}};return e.jsxs(X,q(E({},J(i)),{children:[e.jsx("p",{className:"ant-upload-drag-icon",children:e.jsx(x.InboxOutlined,{})}),e.jsxs("p",{className:"ant-upload-text",children:[" ",b("Click or drag file to this area to upload")]})]}))},Y=()=>{const{t:a}=F(),b=r.useAPIClient(),[i,c]=k.useState([]),[u,h]=k.useState(!1),[f,w]=k.useState(!1),{modal:v,notification:t}=l.App.useApp(),s=k.useMemo(()=>b.resource("backupFiles"),[b]),g=k.useCallback(()=>T(this,null,function*(){yield n()}),[]);r.useNoticeSub("backup",o=>{(t[o.level]||t.info)({key:"backup",message:o.msg}),g()}),k.useEffect(()=>{n()},[]);const n=()=>T(this,null,function*(){h(!0);const{data:o}=yield s.list();c(o.data),h(!1)}),d=o=>T(this,null,function*(){w(o.name);const y=yield b.request({url:"backupFiles:download",method:"get",params:{filterByTk:o.name},responseType:"blob",onDownloadProgress:O=>{const S=Math.round(O.loaded*100/O.total);S>=100?t.success({key:"downloadBackup",message:e.jsx("span",{children:a("Downloaded success!")}),duration:1}):t.info({key:"downloadBackup",message:e.jsxs("span",{children:[a("Downloading ")+S+"%","    ",e.jsx(l.Spin,{indicator:e.jsx(x.LoadingOutlined,{style:{fontSize:24},spin:!0})})]}),duration:0})}});w(!1);const B=new Blob([y.data]);K.saveAs(B,o.name)}),C=o=>{v.confirm({title:a("Delete record",{ns:"core"}),content:a("Are you sure you want to delete it?",{ns:"core"}),onOk:()=>T(this,null,function*(){yield s.destroy({filterByTk:o.name}),yield n(),l.message.success(a("Deleted successfully"))})})};return e.jsx("div",{children:e.jsxs(l.Card,{bordered:!1,children:[e.jsxs(l.Space,{style:{float:"right",marginBottom:16},children:[e.jsx(l.Button,{onClick:g,icon:e.jsx(x.ReloadOutlined,{}),children:a("Refresh")}),e.jsx(G,{upload:!0,title:e.jsxs(e.Fragment,{children:[e.jsx(x.UploadOutlined,{})," ",a("Restore backup from local")]})}),e.jsx(Q,{refresh:g})]}),e.jsx(l.Table,{dataSource:i,loading:u,columns:[{title:a("Backup file"),dataIndex:"name",width:400,onCell:o=>o.inProgress?{colSpan:4}:{},render:(o,y)=>y.inProgress?e.jsxs("div",{style:{color:"rgba(0, 0, 0, 0.88)"},children:[o,"(",a("Backing up"),"...)"]}):y.status==="error"?e.jsxs("div",{style:{color:"red"},children:[o,"(",a("Error"),")"]}):e.jsx("div",{children:o})},{title:a("File size"),dataIndex:"fileSize",onCell:o=>o.inProgress?{colSpan:0}:{}},{title:a("Created at",{ns:"core"}),dataIndex:"createdAt",onCell:o=>o.inProgress?{colSpan:0}:{},render:o=>e.jsx(r.DatePicker.ReadPretty,{value:o,showTime:!0})},{title:a("Actions",{ns:"core"}),dataIndex:"actions",onCell:o=>o.inProgress?{colSpan:0}:{},render:(o,y)=>e.jsxs(l.Space,{split:e.jsx(l.Divider,{type:"vertical"}),children:[y.status!=="error"&&e.jsx(G,{ButtonComponent:"a",title:a("Restore"),fileData:y}),y.status!=="error"&&e.jsx("a",{type:"link",onClick:()=>d(y),children:a("Download")}),e.jsx("a",{onClick:()=>C(y),children:a("Delete")})]})}]})]})})},_=function(a){return e.jsx(r.SchemaComponentOptions,{children:a.children})};_.displayName="DuplicatorProvider";class N extends r.Plugin{load(){return T(this,null,function*(){this.app.use(_),this.app.systemSettingsManager.add("system-services."+I,{title:this.t("Backup & Restore"),icon:"CloudServerOutlined",Component:Y,aclSnippet:"pm.backup.restore"})})}}p.PluginBackupRestoreClient=N,p.default=N,Object.defineProperties(p,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
@@ -1,14 +1,14 @@
1
1
  module.exports = {
2
2
  "react": "18.3.1",
3
- "@tachybase/client": "1.0.6",
4
- "@tachybase/components": "1.0.6",
3
+ "@tachybase/client": "1.0.18",
4
+ "@tachybase/components": "1.0.18",
5
5
  "@ant-design/icons": "5.5.2",
6
6
  "antd": "5.22.5",
7
- "@tachybase/server": "1.0.6",
8
- "@tachybase/utils": "1.0.6",
9
- "@tachybase/database": "1.0.6",
7
+ "@tachybase/server": "1.0.18",
8
+ "@tachybase/utils": "1.0.18",
9
+ "@tachybase/database": "1.0.18",
10
10
  "dayjs": "1.11.13",
11
11
  "lodash": "4.17.21",
12
12
  "react-i18next": "15.2.0",
13
- "@tachybase/actions": "1.0.6"
13
+ "@tachybase/actions": "1.0.18"
14
14
  };
@@ -10,6 +10,7 @@
10
10
  "Configuration": "Configuration",
11
11
  "Delete": "Delete",
12
12
  "Deleted successfully": "Deleted successfully",
13
+ "Done": "Done",
13
14
  "Download": "Download",
14
15
  "File size": "File size",
15
16
  "Learn more": "Learn more",
@@ -12,6 +12,7 @@
12
12
  "Configuration": "配置",
13
13
  "Delete": "删除",
14
14
  "Deleted successfully": "删除成功",
15
+ "Done": "完成",
15
16
  "Download": "下载",
16
17
  "File size": "文件大小",
17
18
  "Learn more": "了解更多",
@@ -1 +1 @@
1
- {"name":"@hapi/topo","description":"Topological sorting with grouping support","version":"6.0.2","repository":"git://github.com/hapijs/topo","main":"lib/index.js","types":"lib/index.d.ts","files":["lib"],"keywords":["topological","sort","toposort","topsort"],"eslintConfig":{"extends":["plugin:@hapi/module"]},"dependencies":{"@hapi/hoek":"^11.0.2"},"devDependencies":{"@hapi/code":"^9.0.3","@hapi/eslint-plugin":"*","@hapi/lab":"^25.1.2","@types/node":"^17.0.31","typescript":"~4.6.4"},"scripts":{"test":"lab -a @hapi/code -t 100 -L -Y","test-cov-html":"lab -a @hapi/code -t 100 -L -r html -o coverage.html"},"license":"BSD-3-Clause","_lastModified":"2025-04-02T02:57:13.012Z"}
1
+ {"name":"@hapi/topo","description":"Topological sorting with grouping support","version":"6.0.2","repository":"git://github.com/hapijs/topo","main":"lib/index.js","types":"lib/index.d.ts","files":["lib"],"keywords":["topological","sort","toposort","topsort"],"eslintConfig":{"extends":["plugin:@hapi/module"]},"dependencies":{"@hapi/hoek":"^11.0.2"},"devDependencies":{"@hapi/code":"^9.0.3","@hapi/eslint-plugin":"*","@hapi/lab":"^25.1.2","@types/node":"^17.0.31","typescript":"~4.6.4"},"scripts":{"test":"lab -a @hapi/code -t 100 -L -Y","test-cov-html":"lab -a @hapi/code -t 100 -L -r html -o coverage.html"},"license":"BSD-3-Clause","_lastModified":"2025-04-18T20:33:17.453Z"}
@@ -1 +1 @@
1
- {"name":"archiver","version":"5.3.2","description":"a streaming interface for archive generation","homepage":"https://github.com/archiverjs/node-archiver","author":{"name":"Chris Talkington","url":"http://christalkington.com/"},"repository":{"type":"git","url":"https://github.com/archiverjs/node-archiver.git"},"bugs":{"url":"https://github.com/archiverjs/node-archiver/issues"},"license":"MIT","main":"index.js","files":["index.js","lib"],"engines":{"node":">= 10"},"scripts":{"test":"mocha --reporter dot","bench":"node benchmark/simple/pack-zip.js"},"dependencies":{"archiver-utils":"^2.1.0","async":"^3.2.4","buffer-crc32":"^0.2.1","readable-stream":"^3.6.0","readdir-glob":"^1.1.2","tar-stream":"^2.2.0","zip-stream":"^4.1.0"},"devDependencies":{"archiver-jsdoc-theme":"^1.1.3","chai":"^4.3.7","jsdoc":"^3.6.4","mkdirp":"^2.1.5","mocha":"^9.0.2","rimraf":"^4.3.1","stream-bench":"^0.1.2","tar":"^6.1.13","yauzl":"^2.9.0"},"keywords":["archive","archiver","stream","zip","tar"],"publishConfig":{"registry":"https://registry.npmjs.org/"},"_lastModified":"2025-04-02T02:57:12.820Z"}
1
+ {"name":"archiver","version":"5.3.2","description":"a streaming interface for archive generation","homepage":"https://github.com/archiverjs/node-archiver","author":{"name":"Chris Talkington","url":"http://christalkington.com/"},"repository":{"type":"git","url":"https://github.com/archiverjs/node-archiver.git"},"bugs":{"url":"https://github.com/archiverjs/node-archiver/issues"},"license":"MIT","main":"index.js","files":["index.js","lib"],"engines":{"node":">= 10"},"scripts":{"test":"mocha --reporter dot","bench":"node benchmark/simple/pack-zip.js"},"dependencies":{"archiver-utils":"^2.1.0","async":"^3.2.4","buffer-crc32":"^0.2.1","readable-stream":"^3.6.0","readdir-glob":"^1.1.2","tar-stream":"^2.2.0","zip-stream":"^4.1.0"},"devDependencies":{"archiver-jsdoc-theme":"^1.1.3","chai":"^4.3.7","jsdoc":"^3.6.4","mkdirp":"^2.1.5","mocha":"^9.0.2","rimraf":"^4.3.1","stream-bench":"^0.1.2","tar":"^6.1.13","yauzl":"^2.9.0"},"keywords":["archive","archiver","stream","zip","tar"],"publishConfig":{"registry":"https://registry.npmjs.org/"},"_lastModified":"2025-04-18T20:33:17.269Z"}
@@ -1 +1 @@
1
- {"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"1.0.4","main":"index.js","keywords":["mkdir","directory","make dir","make","dir","recursive","native"],"repository":{"type":"git","url":"https://github.com/isaacs/node-mkdirp.git"},"scripts":{"test":"tap","snap":"tap","preversion":"npm test","postversion":"npm publish","postpublish":"git push origin --follow-tags"},"tap":{"check-coverage":true,"coverage-map":"map.js"},"devDependencies":{"require-inject":"^1.4.4","tap":"^14.10.7"},"bin":"bin/cmd.js","license":"MIT","engines":{"node":">=10"},"files":["bin","lib","index.js"],"_lastModified":"2025-04-02T02:57:12.916Z"}
1
+ {"name":"mkdirp","description":"Recursively mkdir, like `mkdir -p`","version":"1.0.4","main":"index.js","keywords":["mkdir","directory","make dir","make","dir","recursive","native"],"repository":{"type":"git","url":"https://github.com/isaacs/node-mkdirp.git"},"scripts":{"test":"tap","snap":"tap","preversion":"npm test","postversion":"npm publish","postpublish":"git push origin --follow-tags"},"tap":{"check-coverage":true,"coverage-map":"map.js"},"devDependencies":{"require-inject":"^1.4.4","tap":"^14.10.7"},"bin":"bin/cmd.js","license":"MIT","engines":{"node":">=10"},"files":["bin","lib","index.js"],"_lastModified":"2025-04-18T20:33:17.357Z"}
@@ -1 +1 @@
1
- {"name":"semver","version":"7.6.3","description":"The semantic version parser used by npm.","main":"index.js","scripts":{"test":"tap","snap":"tap","lint":"eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"","postlint":"template-oss-check","lintfix":"npm run lint -- --fix","posttest":"npm run lint","template-oss-apply":"template-oss-apply --force"},"devDependencies":{"@npmcli/eslint-config":"^4.0.0","@npmcli/template-oss":"4.22.0","benchmark":"^2.1.4","tap":"^16.0.0"},"license":"ISC","repository":{"type":"git","url":"git+https://github.com/npm/node-semver.git"},"bin":{"semver":"bin/semver.js"},"files":["bin/","lib/","classes/","functions/","internal/","ranges/","index.js","preload.js","range.bnf"],"tap":{"timeout":30,"coverage-map":"map.js","nyc-arg":["--exclude","tap-snapshots/**"]},"engines":{"node":">=10"},"author":"GitHub Inc.","templateOSS":{"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten.","version":"4.22.0","engines":">=10","distPaths":["classes/","functions/","internal/","ranges/","index.js","preload.js","range.bnf"],"allowPaths":["/classes/","/functions/","/internal/","/ranges/","/index.js","/preload.js","/range.bnf","/benchmarks"],"publish":"true"},"_lastModified":"2025-04-02T02:57:13.246Z"}
1
+ {"name":"semver","version":"7.6.3","description":"The semantic version parser used by npm.","main":"index.js","scripts":{"test":"tap","snap":"tap","lint":"eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"","postlint":"template-oss-check","lintfix":"npm run lint -- --fix","posttest":"npm run lint","template-oss-apply":"template-oss-apply --force"},"devDependencies":{"@npmcli/eslint-config":"^4.0.0","@npmcli/template-oss":"4.22.0","benchmark":"^2.1.4","tap":"^16.0.0"},"license":"ISC","repository":{"type":"git","url":"git+https://github.com/npm/node-semver.git"},"bin":{"semver":"bin/semver.js"},"files":["bin/","lib/","classes/","functions/","internal/","ranges/","index.js","preload.js","range.bnf"],"tap":{"timeout":30,"coverage-map":"map.js","nyc-arg":["--exclude","tap-snapshots/**"]},"engines":{"node":">=10"},"author":"GitHub Inc.","templateOSS":{"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten.","version":"4.22.0","engines":">=10","distPaths":["classes/","functions/","internal/","ranges/","index.js","preload.js","range.bnf"],"allowPaths":["/classes/","/functions/","/internal/","/ranges/","/index.js","/preload.js","/range.bnf","/benchmarks"],"publish":"true"},"_lastModified":"2025-04-18T20:33:17.681Z"}
@@ -1 +1 @@
1
- {"name":"yauzl","version":"3.2.0","description":"yet another unzip library for node","engines":{"node":">=12"},"main":"index.js","scripts":{"test":"node test/test.js"},"repository":{"type":"git","url":"git+https://github.com/thejoshwolfe/yauzl.git"},"keywords":["unzip","zip","stream","archive","file"],"author":"Josh Wolfe <thejoshwolfe@gmail.com>","license":"MIT","bugs":{"url":"https://github.com/thejoshwolfe/yauzl/issues"},"homepage":"https://github.com/thejoshwolfe/yauzl","dependencies":{"buffer-crc32":"~0.2.3","pend":"~1.2.0"},"devDependencies":{"bl":"^6.0.11"},"files":["fd-slicer.js","index.js"],"_lastModified":"2025-04-02T02:57:13.407Z"}
1
+ {"name":"yauzl","version":"3.2.0","description":"yet another unzip library for node","engines":{"node":">=12"},"main":"index.js","scripts":{"test":"node test/test.js"},"repository":{"type":"git","url":"git+https://github.com/thejoshwolfe/yauzl.git"},"keywords":["unzip","zip","stream","archive","file"],"author":"Josh Wolfe <thejoshwolfe@gmail.com>","license":"MIT","bugs":{"url":"https://github.com/thejoshwolfe/yauzl/issues"},"homepage":"https://github.com/thejoshwolfe/yauzl","dependencies":{"buffer-crc32":"~0.2.3","pend":"~1.2.0"},"devDependencies":{"bl":"^6.0.11"},"files":["fd-slicer.js","index.js"],"_lastModified":"2025-04-18T20:33:17.841Z"}
@@ -16,6 +16,11 @@ type BackUpStatusDoing = {
16
16
  inProgress: true;
17
17
  status: 'in_progress';
18
18
  };
19
+ type BackUpStatusError = {
20
+ name: string;
21
+ createdAt: Date;
22
+ status: 'error';
23
+ };
19
24
  export declare class Dumper extends AppMigrator {
20
25
  static dumpTasks: Map<string, Promise<any>>;
21
26
  direction: "dump";
@@ -26,7 +31,7 @@ export declare class Dumper extends AppMigrator {
26
31
  };
27
32
  };
28
33
  static getTaskPromise(taskId: string): Promise<any> | undefined;
29
- static getFileStatus(filePath: string): Promise<BackUpStatusOk | BackUpStatusDoing>;
34
+ static getFileStatus(filePath: string): Promise<BackUpStatusOk | BackUpStatusDoing | BackUpStatusError>;
30
35
  static generateFileName(): string;
31
36
  writeSQLContent(key: string, data: {
32
37
  sql: string | string[];
@@ -50,8 +55,9 @@ export declare class Dumper extends AppMigrator {
50
55
  backUpFilePath(fileName: string, appName?: string): string;
51
56
  lockFilePath(fileName: string, appName?: string): string;
52
57
  writeLockFile(fileName: string, appName?: string): Promise<void>;
53
- cleanLockFile(fileName: string, appName?: string): Promise<void>;
54
- runDumpTask(options: Omit<DumpOptions, 'fileName'>): Promise<string>;
58
+ cleanLockFile(fileName: string, appName: string): Promise<void>;
59
+ getLockFile(appName: string): Promise<string>;
60
+ runDumpTask(options: DumpOptions): Promise<void>;
55
61
  dumpableCollectionsGroupByGroup(): Promise<{
56
62
  [x: string]: Pick<any, string>[];
57
63
  }>;
@@ -36,7 +36,6 @@ var import_path = __toESM(require("path"));
36
36
  var process = __toESM(require("process"));
37
37
  var import_stream = __toESM(require("stream"));
38
38
  var import_util = __toESM(require("util"));
39
- var import_worker_threads = require("worker_threads");
40
39
  var import_database = require("@tachybase/database");
41
40
  var import_archiver = __toESM(require("archiver"));
42
41
  var import_dayjs = __toESM(require("dayjs"));
@@ -60,11 +59,19 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
60
59
  const fileName = import_path.default.basename(filePath);
61
60
  return import_fs.default.promises.stat(lockFile).then((lockFileStat) => {
62
61
  if (lockFileStat.isFile()) {
63
- return {
64
- name: fileName,
65
- inProgress: true,
66
- status: "in_progress"
67
- };
62
+ if (lockFileStat.ctime.getTime() < Date.now() - 2 * 60 * 60 * 1e3) {
63
+ return {
64
+ name: fileName,
65
+ createdAt: lockFileStat.ctime,
66
+ status: "error"
67
+ };
68
+ } else {
69
+ return {
70
+ name: fileName,
71
+ inProgress: true,
72
+ status: "in_progress"
73
+ };
74
+ }
68
75
  } else {
69
76
  throw new Error("Lock file is not a file");
70
77
  }
@@ -187,35 +194,18 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
187
194
  const filePath = this.lockFilePath(fileName, appName);
188
195
  await import_promises.default.unlink(filePath);
189
196
  }
190
- async runDumpTask(options) {
197
+ async getLockFile(appName) {
191
198
  const backupFileName = _Dumper.generateFileName();
192
- await this.writeLockFile(backupFileName, options.appName);
193
- if (import_worker_threads.isMainThread) {
194
- const promise = this.dump({
195
- groups: options.groups,
196
- fileName: backupFileName,
197
- appName: options.appName
198
- }).finally(() => {
199
- this.cleanLockFile(backupFileName, options.appName);
200
- _Dumper.dumpTasks.delete(backupFileName);
201
- this.app.noticeManager.notify("backup", { msg: "Done" });
202
- });
203
- _Dumper.dumpTasks.set(backupFileName, promise);
204
- } else {
205
- try {
206
- await this.dump({
207
- groups: options.groups,
208
- fileName: backupFileName,
209
- appName: options.appName
210
- });
211
- } catch (err) {
212
- throw err;
213
- } finally {
214
- this.cleanLockFile(backupFileName, options.appName);
215
- }
216
- }
199
+ await this.writeLockFile(backupFileName, appName);
217
200
  return backupFileName;
218
201
  }
202
+ async runDumpTask(options) {
203
+ await this.dump({
204
+ groups: options.groups,
205
+ fileName: options.fileName,
206
+ appName: options.appName
207
+ });
208
+ }
219
209
  async dumpableCollectionsGroupByGroup() {
220
210
  return (0, import_lodash.default)(await this.dumpableCollections()).map((c) => import_lodash.default.pick(c, ["name", "group", "origin", "title", "isView", "inherits"])).groupBy("group").mapValues((items) => import_lodash.default.sortBy(items, (item) => item.name)).value();
221
211
  }
@@ -115,31 +115,45 @@ var backup_files_default = {
115
115
  async create(ctx, next) {
116
116
  var _a, _b;
117
117
  const data = ctx.request.body;
118
- let taskId;
119
118
  const app = ctx.app;
120
119
  if (data.method === "worker" && !((_a = app.worker) == null ? void 0 : _a.available)) {
121
120
  ctx.throw(500, ctx.t("No worker thread", { ns: "worker-thread" }));
122
121
  return next();
123
122
  }
124
123
  let useWorker = data.method === "worker" || data.method === "priority" && ((_b = app.worker) == null ? void 0 : _b.available);
124
+ const dumper = new import_dumper.Dumper(ctx.app);
125
+ const taskId = await dumper.getLockFile(ctx.app.name);
125
126
  if (useWorker) {
126
- try {
127
- taskId = await app.worker.callPluginMethod({
128
- plugin: import_server2.default,
129
- method: "workerCreateBackUp",
130
- params: {
131
- dataTypes: data.dataTypes
132
- },
133
- // 目前限制方法并发为1
134
- concurrency: 1
135
- });
136
- app.noticeManager.notify("backup", { level: "info", msg: ctx.t("Done") });
137
- } catch (error) {
138
- ctx.throw(500, ctx.t(error.message, { ns: "worker-thread" }));
139
- }
127
+ app.worker.callPluginMethod({
128
+ plugin: import_server2.default,
129
+ method: "workerCreateBackUp",
130
+ params: {
131
+ dataTypes: data.dataTypes,
132
+ appName: ctx.app.name,
133
+ filename: taskId
134
+ },
135
+ // 目前限制方法并发为1
136
+ concurrency: 1
137
+ }).then((res) => {
138
+ app.noticeManager.notify("backup", { level: "info", msg: ctx.t("Done", { ns: "backup" }) });
139
+ }).catch((error) => {
140
+ app.noticeManager.notify("backup", { level: "error", msg: error.message });
141
+ }).finally(() => {
142
+ dumper.cleanLockFile(taskId, ctx.app.name);
143
+ });
140
144
  } else {
141
145
  const plugin = app.pm.get(import_server2.default);
142
- taskId = await plugin.workerCreateBackUp(data);
146
+ plugin.workerCreateBackUp({
147
+ dataTypes: data.dataTypes,
148
+ appName: ctx.app.name,
149
+ filename: taskId
150
+ }).then((res) => {
151
+ app.noticeManager.notify("backup", { level: "info", msg: ctx.t("Done", { ns: "backup" }) });
152
+ }).catch((error) => {
153
+ app.noticeManager.notify("backup", { level: "error", msg: error.message });
154
+ }).finally(() => {
155
+ dumper.cleanLockFile(taskId, ctx.app.name);
156
+ });
143
157
  }
144
158
  ctx.body = {
145
159
  key: taskId
@@ -4,5 +4,7 @@ export default class PluginBackupRestoreServer extends Plugin {
4
4
  load(): Promise<void>;
5
5
  workerCreateBackUp(data: {
6
6
  dataTypes: string[];
7
- }): Promise<string>;
7
+ appName: string;
8
+ filename: string;
9
+ }): Promise<void>;
8
10
  }
@@ -44,10 +44,10 @@ class PluginBackupRestoreServer extends import_server.Plugin {
44
44
  this.app.resourcer.define(import_backup_files.default);
45
45
  }
46
46
  async workerCreateBackUp(data) {
47
- const dumper = new import_dumper.Dumper(this.app);
48
- return dumper.runDumpTask({
47
+ await new import_dumper.Dumper(this.app).runDumpTask({
49
48
  groups: new Set(data.dataTypes),
50
- appName: this.app.name
49
+ appName: data.appName,
50
+ fileName: data.filename
51
51
  });
52
52
  }
53
53
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tachybase/module-backup",
3
3
  "displayName": "App backup & restore",
4
- "version": "1.0.6",
4
+ "version": "1.0.18",
5
5
  "description": "Backup and restore applications for scenarios such as application replication, migration, and upgrades.",
6
6
  "keywords": [
7
7
  "System management"
@@ -30,16 +30,16 @@
30
30
  "semver": "^7.6.3",
31
31
  "tar": "^6.2.1",
32
32
  "yauzl": "^3.2.0",
33
- "@tachybase/components": "1.0.6",
34
- "@tachybase/module-worker-thread": "1.0.6"
33
+ "@tachybase/components": "1.0.18",
34
+ "@tachybase/module-worker-thread": "1.0.18"
35
35
  },
36
36
  "peerDependencies": {
37
- "@tachybase/actions": "1.0.6",
38
- "@tachybase/client": "1.0.6",
39
- "@tachybase/server": "1.0.6",
40
- "@tachybase/database": "1.0.6",
41
- "@tachybase/test": "1.0.6",
42
- "@tachybase/utils": "1.0.6"
37
+ "@tachybase/actions": "1.0.18",
38
+ "@tachybase/client": "1.0.18",
39
+ "@tachybase/database": "1.0.18",
40
+ "@tachybase/test": "1.0.18",
41
+ "@tachybase/utils": "1.0.18",
42
+ "@tachybase/server": "1.0.18"
43
43
  },
44
44
  "description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
45
45
  "displayName.zh-CN": "应用的备份与还原",