@tachybase/module-backup 0.23.48 → 1.0.6

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,M,a,P){"use strict";var Z=Object.defineProperty,R=Object.defineProperties;var ee=Object.getOwnPropertyDescriptors;var z=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(z)for(var e of z(r))oe.call(r,e)&&W(p,e,r[e]);return p},D=(p,r)=>R(p,ee(r));var B=(p,r,e)=>new Promise((y,L)=>{var M=C=>{try{P(e.next(C))}catch(x){L(x)}},a=C=>{try{P(e.throw(C))}catch(x){L(x)}},P=C=>C.done?y(C.value):Promise.resolve(C.value).then(M,a);P((e=e.apply(p,r)).next())});var C=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{},x={exports:{}};(function(l,g){(function(c,i){i()})(C,function(){function c(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 i(t,s,b){var n=new XMLHttpRequest;n.open("GET",t),n.responseType="blob",n.onload=function(){v(n.response,s,b)},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(b){}return 200<=s.status&&299>=s.status}function h(t){try{t.dispatchEvent(new MouseEvent("click"))}catch(b){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 C=="object"&&C.global===C?C: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,b){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)?i(t,s,b):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,b){if(s=s||t.name||"download",typeof t!="string")navigator.msSaveOrOpenBlob(c(t,b),s);else if(u(t))i(t,s,b);else{var n=document.createElement("a");n.href=t,n.target="_blank",setTimeout(function(){h(n)})}}:function(t,s,b,n){if(n=n||open("","_blank"),n&&(n.document.title=n.document.body.innerText="downloading..."),typeof t=="string")return i(t,s,b);var d=t.type==="application/octet-stream",m=/constructor/i.test(f.HTMLElement)||f.safari,o=/CriOS\/[\d]+/.test(navigator.userAgent);if((o||d&&m||w)&&typeof FileReader!="undefined"){var k=new FileReader;k.onloadend=function(){var T=k.result;T=o?T:T.replace(/^data:[^;]*;/,"data:attachment/file;"),n?n.location.href=T:location=T,n=null},k.readAsDataURL(t)}else{var S=f.URL||f.webkitURL,A=S.createObjectURL(t);n?n.location=A:location.href=A,n=null,setTimeout(function(){S.revokeObjectURL(A)},4e4)}});f.saveAs=v.saveAs=v,l.exports=v})})(x);var K=x.exports;const I="backup";function E(){return P.useTranslation(I,{nsMode:"fallback"})}const{Dragger:X}=a.Upload;function J(l){const g=i=>{var u;(u=l.onChange)==null||u.call(l,i)},c=r.useAPIClient();return D(q({},l),{customRequest({action:i,data:u,file:h,filename:f,headers:w,onError:v,onProgress:t,onSuccess:s,withCredentials:b}){const n=new FormData;return u&&Object.keys(u).forEach(d=>{n.append(d,u[d])}),n.append(f,h),c.axios.post(i,n,{withCredentials:b,headers:w,onUploadProgress:({total:d,loaded:m})=>{t({percent:Math.round(m/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=l=>{const{collectionsData:g}=l,{t:c}=E(),[i,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=()=>B(this,null,function*(){if(l.isBackup){const o=yield t.dumpableCollections();f(o==null?void 0:o.data),u(!0)}u(!0)}),b=()=>{u(!1)},n=()=>{u(!1)},d=[{title:c("Collection"),dataIndex:"collection",key:"collection",render:(o,k)=>{const S=v(k.title);return k.name===S?S:e.jsxs("div",{children:[k.name," ",e.jsxs("span",{style:{color:"rgba(0, 0, 0, 0.3)",fontSize:"0.9em"},children:["(",v(k.title),")"]})]})}},{title:c("Origin"),dataIndex:"origin",key:"origin",width:"50%"}],m=Object.keys(h||{}).map(o=>({key:o,label:c(`${o}.title`),children:e.jsxs(e.Fragment,{children:[e.jsx(a.Alert,{style:{marginBottom:16},message:c(`${o}.description`)}),e.jsx(a.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:c("Learn more")}),e.jsx(a.Modal,{title:c("Backup instructions"),width:"80vw",open:i,footer:null,onOk:b,onCancel:n,children:e.jsx(a.Tabs,{defaultActiveKey:"required",items:m})})]})},G=({ButtonComponent:l=a.Button,title:g,upload:c=!1,fileData:i})=>{const{t:u}=E(),[h,f]=y.useState(["required"]),[w,v]=y.useState(!1),[t,s]=y.useState(null),[b,n]=y.useState(!1),d=r.useAPIClient(),m=y.useMemo(()=>d.resource("backupFiles"),[d]),[o,k]=y.useState([]);y.useEffect(()=>{k(Object.keys((t==null?void 0:t.dumpableCollectionsGroupByGroup)||[]).map(O=>({value:O,label:u(`${O}.title`),disabled:["required","skipped"].includes(O)})))},[t]);const S=()=>B(this,null,function*(){var O,H,$;if(v(!0),!c){n(!0);const{data:F}=yield m.get({filterByTk:i.name});k(Object.keys(((H=(O=F==null?void 0:F.data)==null?void 0:O.meta)==null?void 0:H.dumpableCollectionsGroupByGroup)||[]).map(j=>({value:j,label:u(`${j}.title`),disabled:["required","skipped"].includes(j)}))),s(($=F==null?void 0:F.data)==null?void 0:$.meta),n(!1)}}),A=()=>{m.restore({values:{dataTypes:h,filterByTk:i==null?void 0:i.name,key:t==null?void 0:t.key}}),v(!1)},T=()=>{v(!1),s(null),f(["required"])};return e.jsxs(e.Fragment,{children:[e.jsx(l,{onClick:S,children:g}),e.jsx(a.Modal,{title:u("Restore"),width:800,footer:c&&!t?null:void 0,open:w,onOk:A,onCancel:T,children:e.jsxs(a.Spin,{spinning:b,children:[c&&!t&&e.jsx(V,{setRestoreData:s}),(!c||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:O=>f(O)})})},"dataType")]]})})]})},Q=({ButtonComponent:l=a.Button,refresh:g})=>{const{t:c}=E(),[i,u]=y.useState(!1),[h,f]=y.useState(["required"]),w=r.useAPIClient(),{notification:v}=a.App.useApp(),[t,s]=y.useState([]),b=()=>B(this,null,function*(){const{data:m}=yield w.resource("backupFiles").dumpableCollections();s(Object.keys(m||[]).map(o=>({value:o,label:c(`${o}.title`),disabled:["required","skipped"].includes(o)}))),u(!0)}),n=m=>{w.request({url:"backupFiles:create",method:"post",data:{dataTypes:h,method:m}}).finally(()=>{v.destroy("backup")}),v.info({key:"backup",message:e.jsxs("span",{children:[c("Processing..."),"    ",e.jsx(a.Spin,{indicator:e.jsx(M.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(l,{icon:e.jsx(M.PlusOutlined,{}),type:"primary",onClick:b,children:c("New backup")}),e.jsxs(a.Modal,{title:c("New backup"),width:800,open:i,onCancel:d,footer:[e.jsxs(a.Row,{gutter:16,justify:"end",align:"middle",children:[e.jsx(a.Col,{children:e.jsx(a.Button,{onClick:d,children:c("Cancel")},"cancel")}),e.jsx(a.Col,{children:e.jsx(a.Dropdown.Button,{type:"primary",onClick:()=>n("priority"),overlay:e.jsxs(a.Menu,{children:[e.jsx(a.Menu.Item,{onClick:()=>n("main"),children:c("Self backup")},"main"),e.jsx(a.Menu.Item,{onClick:()=>n("worker"),children:c("Worker backup")},"worker")]}),children:c("Backup")},"submit")})]})],children:[e.jsxs("strong",{style:{fontWeight:600,display:"block",margin:"16px 0 8px"},children:[c("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:m=>f(m),value:h})})]})]})},V=l=>{const{t:g}=E(),c={multiple:!1,action:"/backupFiles:upload",onChange(i){var h,f,w;i.fileList.length>1&&i.fileList.splice(0,i.fileList.length-1);const{status:u}=i.file;u==="done"?(a.message.success(`${i.file.name} `+g("file uploaded successfully")),l.setRestoreData(D(q({},(f=(h=i.file.response)==null?void 0:h.data)==null?void 0:f.meta),{key:(w=i.file.response)==null?void 0:w.data.key}))):u==="error"&&a.message.error(`${i.file.name} `+g("file upload failed"))},onDrop(i){console.log("Dropped files",i.dataTransfer.files)}};return e.jsxs(X,D(q({},J(c)),{children:[e.jsx("p",{className:"ant-upload-drag-icon",children:e.jsx(M.InboxOutlined,{})}),e.jsxs("p",{className:"ant-upload-text",children:[" ",g("Click or drag file to this area to upload")]})]}))},Y=()=>{const{t:l}=E(),g=r.useAPIClient(),[c,i]=y.useState([]),[u,h]=y.useState(!1),[f,w]=y.useState(!1),{modal:v,notification:t}=a.App.useApp(),s=y.useMemo(()=>g.resource("backupFiles"),[g]),b=y.useCallback(()=>B(this,null,function*(){yield n()}),[]);r.useNoticeSub("backup",o=>{(t[o.level]||t.info)({key:"backup",message:o.msg}),b()}),y.useEffect(()=>{n()},[]);const n=()=>B(this,null,function*(){h(!0);const{data:o}=yield s.list();i(o.data),h(!1)}),d=o=>B(this,null,function*(){w(o.name);const k=yield g.request({url:"backupFiles:download",method:"get",params:{filterByTk:o.name},responseType:"blob"});w(!1);const S=new Blob([k.data]);K.saveAs(S,o.name)}),m=o=>{v.confirm({title:l("Delete record",{ns:"core"}),content:l("Are you sure you want to delete it?",{ns:"core"}),onOk:()=>B(this,null,function*(){yield s.destroy({filterByTk:o.name}),yield n(),a.message.success(l("Deleted successfully"))})})};return e.jsx("div",{children:e.jsxs(a.Card,{bordered:!1,children:[e.jsxs(a.Space,{style:{float:"right",marginBottom:16},children:[e.jsx(a.Button,{onClick:b,icon:e.jsx(M.ReloadOutlined,{}),children:l("Refresh")}),e.jsx(G,{upload:!0,title:e.jsxs(e.Fragment,{children:[e.jsx(M.UploadOutlined,{})," ",l("Restore backup from local")]})}),e.jsx(Q,{refresh:b})]}),e.jsx(a.Table,{dataSource:c,loading:u,columns:[{title:l("Backup file"),dataIndex:"name",width:400,onCell:o=>o.inProgress?{colSpan:4}:{},render:(o,k)=>k.inProgress?e.jsxs("div",{style:{color:"rgba(0, 0, 0, 0.88)"},children:[o,"(",l("Backing up"),"...)"]}):e.jsx("div",{children:o})},{title:l("File size"),dataIndex:"fileSize",onCell:o=>o.inProgress?{colSpan:0}:{}},{title:l("Created at",{ns:"core"}),dataIndex:"createdAt",onCell:o=>o.inProgress?{colSpan:0}:{},render:o=>e.jsx(r.DatePicker.ReadPretty,{value:o,showTime:!0})},{title:l("Actions",{ns:"core"}),dataIndex:"actions",onCell:o=>o.inProgress?{colSpan:0}:{},render:(o,k)=>e.jsxs(a.Space,{split:e.jsx(a.Divider,{type:"vertical"}),children:[e.jsx(G,{ButtonComponent:"a",title:l("Restore"),fileData:k}),e.jsx("a",{type:"link",onClick:()=>d(k),children:l("Download")}),e.jsx("a",{onClick:()=>m(k),children:l("Delete")})]})}]})]})})},_=function(l){return e.jsx(r.SchemaComponentOptions,{children:l.children})};_.displayName="DuplicatorProvider";class N extends r.Plugin{load(){return B(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,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,14 +1,14 @@
1
1
  module.exports = {
2
2
  "react": "18.3.1",
3
- "@tachybase/client": "0.23.48",
4
- "@tachybase/components": "0.23.48",
3
+ "@tachybase/client": "1.0.6",
4
+ "@tachybase/components": "1.0.6",
5
5
  "@ant-design/icons": "5.5.2",
6
6
  "antd": "5.22.5",
7
- "@tachybase/server": "0.23.48",
8
- "@tachybase/utils": "0.23.48",
9
- "@tachybase/database": "0.23.48",
7
+ "@tachybase/server": "1.0.6",
8
+ "@tachybase/utils": "1.0.6",
9
+ "@tachybase/database": "1.0.6",
10
10
  "dayjs": "1.11.13",
11
11
  "lodash": "4.17.21",
12
12
  "react-i18next": "15.2.0",
13
- "@tachybase/actions": "0.23.48"
13
+ "@tachybase/actions": "1.0.6"
14
14
  };
@@ -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-02-21T11:02:02.757Z"}
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 +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-02-21T11:02:02.537Z"}
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 +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-02-21T11:02:02.659Z"}
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 +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-02-21T11:02:02.993Z"}
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 +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-02-21T11:02:03.155Z"}
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"}
@@ -3,6 +3,7 @@ import { AppMigrator } from './app-migrator';
3
3
  type DumpOptions = {
4
4
  groups: Set<DumpRulesGroupType>;
5
5
  fileName?: string;
6
+ appName?: string;
6
7
  };
7
8
  type BackUpStatusOk = {
8
9
  name: string;
@@ -40,15 +41,16 @@ export declare class Dumper extends AppMigrator {
40
41
  collectionsGroupByDataTypes(): Promise<{
41
42
  [k: string]: any[];
42
43
  }>;
43
- backUpStorageDir(): string;
44
+ backUpStorageDir(appName?: string): string;
44
45
  allBackUpFilePaths(options?: {
45
46
  includeInProgress?: boolean;
46
47
  dir?: string;
48
+ appName?: string;
47
49
  }): Promise<string[]>;
48
- backUpFilePath(fileName: string): string;
49
- lockFilePath(fileName: string): string;
50
- writeLockFile(fileName: string): Promise<void>;
51
- cleanLockFile(fileName: string): Promise<void>;
50
+ backUpFilePath(fileName: string, appName?: string): string;
51
+ lockFilePath(fileName: string, appName?: string): string;
52
+ writeLockFile(fileName: string, appName?: string): Promise<void>;
53
+ cleanLockFile(fileName: string, appName?: string): Promise<void>;
52
54
  runDumpTask(options: Omit<DumpOptions, 'fileName'>): Promise<string>;
53
55
  dumpableCollectionsGroupByGroup(): Promise<{
54
56
  [x: string]: Pick<any, string>[];
@@ -63,7 +65,7 @@ export declare class Dumper extends AppMigrator {
63
65
  dumpCollection(options: {
64
66
  name: string;
65
67
  }): Promise<void>;
66
- packDumpedDir(fileName: string): Promise<{
68
+ packDumpedDir(fileName: string, appName?: string): Promise<{
67
69
  filePath: string;
68
70
  dirname: string;
69
71
  }>;
@@ -134,11 +134,14 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
134
134
  const grouped = import_lodash.default.groupBy(await this.dumpableCollections(), "group");
135
135
  return Object.fromEntries(Object.entries(grouped).map(([key, value]) => [key, value.map((item) => item.name)]));
136
136
  }
137
- backUpStorageDir() {
137
+ backUpStorageDir(appName) {
138
+ if (appName && appName !== "main") {
139
+ return import_path.default.resolve(process.cwd(), "storage", "backups", appName);
140
+ }
138
141
  return import_path.default.resolve(process.cwd(), "storage", "backups");
139
142
  }
140
143
  async allBackUpFilePaths(options) {
141
- const dirname = (options == null ? void 0 : options.dir) || this.backUpStorageDir();
144
+ const dirname = (options == null ? void 0 : options.dir) || this.backUpStorageDir(options == null ? void 0 : options.appName);
142
145
  const includeInProgress = options == null ? void 0 : options.includeInProgress;
143
146
  try {
144
147
  const files = await import_promises.default.readdir(dirname);
@@ -165,34 +168,35 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
165
168
  return [];
166
169
  }
167
170
  }
168
- backUpFilePath(fileName) {
169
- const dirname = this.backUpStorageDir();
171
+ backUpFilePath(fileName, appName) {
172
+ const dirname = this.backUpStorageDir(appName);
170
173
  return import_path.default.resolve(dirname, fileName);
171
174
  }
172
- lockFilePath(fileName) {
175
+ lockFilePath(fileName, appName) {
173
176
  const lockFile = fileName + ".lock";
174
- const dirname = this.backUpStorageDir();
177
+ const dirname = this.backUpStorageDir(appName);
175
178
  return import_path.default.resolve(dirname, lockFile);
176
179
  }
177
- async writeLockFile(fileName) {
178
- const dirname = this.backUpStorageDir();
180
+ async writeLockFile(fileName, appName) {
181
+ const dirname = this.backUpStorageDir(appName);
179
182
  await (0, import_mkdirp.default)(dirname);
180
- const filePath = this.lockFilePath(fileName);
183
+ const filePath = this.lockFilePath(fileName, appName);
181
184
  await import_promises.default.writeFile(filePath, "lock", "utf8");
182
185
  }
183
- async cleanLockFile(fileName) {
184
- const filePath = this.lockFilePath(fileName);
186
+ async cleanLockFile(fileName, appName) {
187
+ const filePath = this.lockFilePath(fileName, appName);
185
188
  await import_promises.default.unlink(filePath);
186
189
  }
187
190
  async runDumpTask(options) {
188
191
  const backupFileName = _Dumper.generateFileName();
189
- await this.writeLockFile(backupFileName);
192
+ await this.writeLockFile(backupFileName, options.appName);
190
193
  if (import_worker_threads.isMainThread) {
191
194
  const promise = this.dump({
192
195
  groups: options.groups,
193
- fileName: backupFileName
196
+ fileName: backupFileName,
197
+ appName: options.appName
194
198
  }).finally(() => {
195
- this.cleanLockFile(backupFileName);
199
+ this.cleanLockFile(backupFileName, options.appName);
196
200
  _Dumper.dumpTasks.delete(backupFileName);
197
201
  this.app.noticeManager.notify("backup", { msg: "Done" });
198
202
  });
@@ -201,12 +205,13 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
201
205
  try {
202
206
  await this.dump({
203
207
  groups: options.groups,
204
- fileName: backupFileName
208
+ fileName: backupFileName,
209
+ appName: options.appName
205
210
  });
206
211
  } catch (err) {
207
212
  throw err;
208
213
  } finally {
209
- this.cleanLockFile(backupFileName);
214
+ this.cleanLockFile(backupFileName, options.appName);
210
215
  }
211
216
  }
212
217
  return backupFileName;
@@ -235,7 +240,7 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
235
240
  });
236
241
  await this.dumpDb(options);
237
242
  const backupFileName = options.fileName || _Dumper.generateFileName();
238
- const filePath = await this.packDumpedDir(backupFileName);
243
+ const filePath = await this.packDumpedDir(backupFileName, options.appName);
239
244
  await this.clearWorkDir();
240
245
  return filePath;
241
246
  }
@@ -380,8 +385,8 @@ const _Dumper = class _Dumper extends import_app_migrator.AppMigrator {
380
385
  }
381
386
  await import_promises.default.writeFile(import_path.default.resolve(collectionDataDir, "meta"), JSON.stringify(meta), "utf8");
382
387
  }
383
- async packDumpedDir(fileName) {
384
- const dirname = this.backUpStorageDir();
388
+ async packDumpedDir(fileName, appName) {
389
+ const dirname = this.backUpStorageDir(appName);
385
390
  await (0, import_mkdirp.default)(dirname);
386
391
  const filePath = import_path.default.resolve(dirname, fileName);
387
392
  const output = import_fs.default.createWriteStream(filePath);
@@ -60,7 +60,8 @@ var backup_files_default = {
60
60
  const { page = import_actions.DEFAULT_PAGE, pageSize = import_actions.DEFAULT_PER_PAGE } = ctx.action.params;
61
61
  const dumper = new import_dumper.Dumper(ctx.app);
62
62
  const backupFiles = await dumper.allBackUpFilePaths({
63
- includeInProgress: true
63
+ includeInProgress: true,
64
+ appName: ctx.app.name
64
65
  });
65
66
  const count = backupFiles.length;
66
67
  const rows = await Promise.all(
@@ -80,7 +81,7 @@ var backup_files_default = {
80
81
  async get(ctx, next) {
81
82
  const { filterByTk } = ctx.action.params;
82
83
  const dumper = new import_dumper.Dumper(ctx.app);
83
- const filePath = dumper.backUpFilePath(filterByTk);
84
+ const filePath = dumper.backUpFilePath(filterByTk, ctx.app.name);
84
85
  async function sendError(message, status = 404) {
85
86
  ctx.body = { status: "error", message };
86
87
  ctx.status = status;
@@ -153,11 +154,14 @@ var backup_files_default = {
153
154
  async download(ctx, next) {
154
155
  const { filterByTk } = ctx.action.params;
155
156
  const dumper = new import_dumper.Dumper(ctx.app);
156
- const filePath = dumper.backUpFilePath(filterByTk);
157
+ const filePath = dumper.backUpFilePath(filterByTk, ctx.app.name);
157
158
  const fileState = await import_dumper.Dumper.getFileStatus(filePath);
158
159
  if (fileState.status !== "ok") {
159
160
  throw new Error(`Backup file ${filterByTk} not found`);
160
161
  }
162
+ const stats = import_node_fs.default.statSync(filePath);
163
+ const fileSize = stats.size;
164
+ ctx.set("Content-Length", fileSize);
161
165
  ctx.attachment(filePath);
162
166
  ctx.body = import_node_fs.default.createReadStream(filePath);
163
167
  await next();
@@ -171,7 +175,7 @@ var backup_files_default = {
171
175
  }
172
176
  if (filterByTk) {
173
177
  const dumper = new import_dumper.Dumper(ctx.app);
174
- return dumper.backUpFilePath(filterByTk);
178
+ return dumper.backUpFilePath(filterByTk, ctx.app.name);
175
179
  }
176
180
  })();
177
181
  if (!filePath) {
@@ -187,7 +191,7 @@ var backup_files_default = {
187
191
  async destroy(ctx, next) {
188
192
  const { filterByTk } = ctx.action.params;
189
193
  const dumper = new import_dumper.Dumper(ctx.app);
190
- const filePath = dumper.backUpFilePath(filterByTk);
194
+ const filePath = dumper.backUpFilePath(filterByTk, ctx.app.name);
191
195
  await import_promises.default.unlink(filePath);
192
196
  ctx.body = {
193
197
  status: "ok"
@@ -46,7 +46,8 @@ class PluginBackupRestoreServer extends import_server.Plugin {
46
46
  async workerCreateBackUp(data) {
47
47
  const dumper = new import_dumper.Dumper(this.app);
48
48
  return dumper.runDumpTask({
49
- groups: new Set(data.dataTypes)
49
+ groups: new Set(data.dataTypes),
50
+ appName: this.app.name
50
51
  });
51
52
  }
52
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": "0.23.48",
4
+ "version": "1.0.6",
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/module-worker-thread": "0.23.48",
34
- "@tachybase/components": "0.23.48"
33
+ "@tachybase/components": "1.0.6",
34
+ "@tachybase/module-worker-thread": "1.0.6"
35
35
  },
36
36
  "peerDependencies": {
37
- "@tachybase/client": "0.23.48",
38
- "@tachybase/server": "0.23.48",
39
- "@tachybase/test": "0.23.48",
40
- "@tachybase/utils": "0.23.48",
41
- "@tachybase/actions": "0.23.48",
42
- "@tachybase/database": "0.23.48"
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"
43
43
  },
44
44
  "description.zh-CN": "备份和还原应用,可用于应用的复制、迁移、升级等场景。",
45
45
  "displayName.zh-CN": "应用的备份与还原",