nuwax-file-server 1.2.4 → 1.2.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.
Files changed (46) hide show
  1. package/README.md +131 -151
  2. package/dist/appConfig/index.js +1 -1
  3. package/dist/cli.js +1 -1
  4. package/dist/config/swagger.js +1 -1
  5. package/dist/env.development +3 -0
  6. package/dist/env.production +3 -0
  7. package/dist/routes/buildRoutes.js +1 -1
  8. package/dist/routes/codeRoutes.js +1 -1
  9. package/dist/routes/computerRoutes.js +1 -1
  10. package/dist/routes/projectRoutes.js +1 -1
  11. package/dist/scheduler/pnpmPruneScheduler.js +2 -2
  12. package/dist/server.js +1 -1
  13. package/dist/service/codeService.js +2 -2
  14. package/dist/service/projectService.js +1 -1
  15. package/dist/utils/build/buildProjectUtils.js +4 -4
  16. package/dist/utils/build/keepAliveDevUtils.js +1 -1
  17. package/dist/utils/build/processManager.js +9 -9
  18. package/dist/utils/build/restartDevUtils.js +1 -1
  19. package/dist/utils/build/startDevUtils.js +1 -1
  20. package/dist/utils/build/stopDevUtils.js +2 -2
  21. package/dist/utils/build/syntaxCheckUtils.js +7 -7
  22. package/dist/utils/buildArg/extraArgsUtils.js +1 -1
  23. package/dist/utils/buildArg/portPool.js +1 -1
  24. package/dist/utils/buildArg/portUtils.js +7 -7
  25. package/dist/utils/buildDependency/dependencyManager.js +17 -17
  26. package/dist/utils/buildJudge/aliveJudgeUtils.js +1 -1
  27. package/dist/utils/buildJudge/restartJudgeUtils.js +1 -1
  28. package/dist/utils/buildPermission/permissionManager.js +3 -3
  29. package/dist/utils/common/npmrcUtils.js +3 -3
  30. package/dist/utils/common/zipUtils.js +1 -1
  31. package/dist/utils/computer/computerFileUtils.js +1 -1
  32. package/dist/utils/computer/computerUtils.js +1 -1
  33. package/dist/utils/envUtils.js +3 -3
  34. package/dist/utils/error/buildErrorParser.js +18 -18
  35. package/dist/utils/error/errorHandler.js +1 -1
  36. package/dist/utils/log/getDevLogUtils.js +2 -2
  37. package/dist/utils/log/logCacheManager.js +2 -2
  38. package/dist/utils/log/logUtils.js +2 -2
  39. package/dist/utils/project/backupUtils.js +1 -1
  40. package/dist/utils/project/copyProjectUtils.js +1 -1
  41. package/dist/utils/project/frameworkDetectorUtils.js +1 -1
  42. package/dist/utils/project/getContentUtils.js +1 -1
  43. package/dist/utils/project/initProjectCleanupUtils.js +1 -1
  44. package/dist/utils/project/uploadAttachmentFileUtils.js +1 -1
  45. package/dist/utils/serviceManager.js +3 -3
  46. package/package.json +2 -2
@@ -1 +1 @@
1
- import{log as S,getCSTTimestampString as _}from"../log/logUtils.js";import{sanitizeSensitivePaths as a}from"../common/sensitiveUtils.js";import L from"../../appConfig/index.js";const o={VALIDATION_ERROR:"VALIDATION_ERROR",BUSINESS_ERROR:"BUSINESS_ERROR",SYSTEM_ERROR:"SYSTEM_ERROR",NETWORK_ERROR:"NETWORK_ERROR",FILE_ERROR:"FILE_ERROR",PROCESS_ERROR:"PROCESS_ERROR",PERMISSION_ERROR:"PERMISSION_ERROR",RESOURCE_ERROR:"RESOURCE_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR"},A={[o.VALIDATION_ERROR]:400,[o.BUSINESS_ERROR]:400,[o.PERMISSION_ERROR]:403,[o.RESOURCE_ERROR]:404,[o.SYSTEM_ERROR]:500,[o.NETWORK_ERROR]:502,[o.FILE_ERROR]:500,[o.PROCESS_ERROR]:500,[o.UNKNOWN_ERROR]:500};class n extends Error{constructor(t,r=o.UNKNOWN_ERROR,R=null,s=null){super(t),this.name="AppError",this.type=r,this.statusCode=R||A[r]||500,this.details=s,this.timestamp=_(),this.isOperational=!0,Error.captureStackTrace(this,this.constructor)}}class E extends n{constructor(t,r=null){super(t,o.VALIDATION_ERROR,400,r),this.name="ValidationError"}}class C extends n{constructor(t,r=null){super(t,o.BUSINESS_ERROR,400,r),this.name="BusinessError"}}class l extends n{constructor(t,r=null){super(t,o.SYSTEM_ERROR,500,r),this.name="SystemError"}}class O extends n{constructor(t,r=null){super(t,o.RESOURCE_ERROR,404,r),this.name="ResourceError"}}class f extends n{constructor(t,r=null){super(t,o.PERMISSION_ERROR,403,r),this.name="PermissionError"}}class h extends n{constructor(t,r=null){super(t,o.FILE_ERROR,500,r),this.name="FileError"}}class g extends n{constructor(t,r=null){super(t,o.PROCESS_ERROR,500,r),this.name="ProcessError"}}function I(e){return a(e)}function u(e){if(!e)return e;if(typeof e=="string")return a(e);if(typeof e=="object"){const t={};for(const[r,R]of Object.entries(e))typeof R=="string"?t[r]=a(R):typeof R=="object"?t[r]=u(R):t[r]=R;return t}return e}function d(e,t=null){const r={success:!1,code:e.code||e.details&&e.details.code||"UNKNOWN_ERROR",error:{type:e.type||o.UNKNOWN_ERROR,message:e.message||"\u672A\u77E5\u9519\u8BEF",timestamp:e.timestamp||_(),requestId:t}};return process.env.NODE_ENV==="development"?(r.error.stack=I(e.stack),r.error.details=u(e.details)):e.details&&(r.error.details=u(e.details)),r}function M(e,t,r,R){let s=e;const c=t.requestId||"unknown",m=t.body?.projectId||t.query?.projectId||"default";if(!(s instanceof n))if(s.name==="ValidationError")s=new E(s.message,s.details);else if(s.name==="MulterError")if(s.code==="LIMIT_FILE_SIZE"){const U=Math.round(L.UPLOAD_MAX_FILE_SIZE_BYTES/1024/1024*10)/10;s=new E("\u6587\u4EF6\u5927\u5C0F\u8D85\u51FA\u9650\u5236",{maxSize:`${U}MB`})}else s.code==="LIMIT_FILE_COUNT"?s=new E("\u6587\u4EF6\u6570\u91CF\u8D85\u51FA\u9650\u5236"):s.code==="LIMIT_UNEXPECTED_FILE"?s=new E("\u6587\u4EF6\u5B57\u6BB5\u540D\u9519\u8BEF\uFF0C\u8BF7\u4F7F\u7528 'file' \u5B57\u6BB5\u4E0A\u4F20\u6587\u4EF6",{expectedField:"file",receivedField:s.field}):s.code==="LIMIT_PART_COUNT"?s=new E("\u8868\u5355\u5B57\u6BB5\u6570\u91CF\u8D85\u51FA\u9650\u5236"):s.code==="LIMIT_FIELD_KEY"?s=new E("\u5B57\u6BB5\u540D\u957F\u5EA6\u8D85\u51FA\u9650\u5236"):s.code==="LIMIT_FIELD_VALUE"?s=new E("\u5B57\u6BB5\u503C\u957F\u5EA6\u8D85\u51FA\u9650\u5236"):s.code==="LIMIT_FIELD_COUNT"?s=new E("\u8868\u5355\u5B57\u6BB5\u6570\u91CF\u8D85\u51FA\u9650\u5236"):s=new E("\u6587\u4EF6\u4E0A\u4F20\u9519\u8BEF: "+s.message,{code:s.code,field:s.field});else s.code==="ENOENT"?s=new O("\u6587\u4EF6\u6216\u76EE\u5F55\u4E0D\u5B58\u5728"):s.code==="EACCES"?s=new f("\u6743\u9650\u4E0D\u8DB3"):s.code==="ECONNREFUSED"?s=new l("\u8FDE\u63A5\u88AB\u62D2\u7EDD",{code:s.code}):s=new l(s.message||"\u7CFB\u7EDF\u5185\u90E8\u9519\u8BEF",{originalError:s.name,code:s.code});const p=s.statusCode>=500?"ERROR":"WARN";S(m,p,`\u9519\u8BEF\u5904\u7406: ${s.message}`,{requestId:c,errorType:s.type,statusCode:s.statusCode,url:t.originalUrl,method:t.method,userAgent:t.headers["user-agent"],ip:t.ip,stack:s.stack,details:s.details});const T=d(s,c);r.status(s.statusCode).json(T)}function P(e,t,r){const R=new O(`\u8DEF\u5F84\u4E0D\u5B58\u5728: ${e.originalUrl}`),s=e.requestId||"unknown";S("default","WARN",`404\u9519\u8BEF: ${e.originalUrl}`,{requestId:s,method:e.method,ip:e.ip,userAgent:e.headers["user-agent"]});const c=d(R,s);t.status(404).json(c)}function w(e){return(t,r,R)=>{Promise.resolve(e(t,r,R)).catch(R)}}function N(e){return e instanceof n?e.type:e.code==="ENOENT"?o.RESOURCE_ERROR:e.code==="EACCES"?o.PERMISSION_ERROR:e.code==="ECONNREFUSED"?o.NETWORK_ERROR:e.name==="ValidationError"?o.VALIDATION_ERROR:o.UNKNOWN_ERROR}const i={counts:new Map,lastReset:Date.now()};function y(e){const t=N(e),r=i.counts.get(t)||0;i.counts.set(t,r+1)}function F(){return{counts:Object.fromEntries(i.counts),lastReset:i.lastReset,totalErrors:Array.from(i.counts.values()).reduce((e,t)=>e+t,0)}}function D(){i.counts.clear(),i.lastReset=Date.now()}export{o as ERROR_TYPES,n as AppError,E as ValidationError,C as BusinessError,l as SystemError,O as ResourceError,f as PermissionError,h as FileError,g as ProcessError,d as formatErrorResponse,M as errorHandler,P as notFoundHandler,w as asyncHandler,N as classifyError,a as sanitizeSensitivePaths,I as sanitizeErrorStack,u as sanitizeErrorDetails,y as recordError,F as getErrorStats,D as resetErrorStats};
1
+ import{log as f,getCSTTimestampString as S}from"../log/logUtils.js";import{sanitizeSensitivePaths as l}from"../common/sensitiveUtils.js";import h from"../../appConfig/index.js";const o={VALIDATION_ERROR:"VALIDATION_ERROR",BUSINESS_ERROR:"BUSINESS_ERROR",SYSTEM_ERROR:"SYSTEM_ERROR",NETWORK_ERROR:"NETWORK_ERROR",FILE_ERROR:"FILE_ERROR",PROCESS_ERROR:"PROCESS_ERROR",PERMISSION_ERROR:"PERMISSION_ERROR",RESOURCE_ERROR:"RESOURCE_ERROR",UNKNOWN_ERROR:"UNKNOWN_ERROR"},F={[o.VALIDATION_ERROR]:400,[o.BUSINESS_ERROR]:400,[o.PERMISSION_ERROR]:403,[o.RESOURCE_ERROR]:404,[o.SYSTEM_ERROR]:500,[o.NETWORK_ERROR]:502,[o.FILE_ERROR]:500,[o.PROCESS_ERROR]:500,[o.UNKNOWN_ERROR]:500};class R extends Error{constructor(s,r=o.UNKNOWN_ERROR,n=null,t=null){super(s),this.name="AppError",this.type=r,this.statusCode=n||F[r]||500,this.details=t,this.timestamp=S(),this.isOperational=!0,Error.captureStackTrace(this,this.constructor)}}class i extends R{constructor(s,r=null){super(s,o.VALIDATION_ERROR,400,r),this.name="ValidationError"}}class g extends R{constructor(s,r=null){super(s,o.BUSINESS_ERROR,400,r),this.name="BusinessError"}}class u extends R{constructor(s,r=null){super(s,o.SYSTEM_ERROR,500,r),this.name="SystemError"}}class d extends R{constructor(s,r=null){super(s,o.RESOURCE_ERROR,404,r),this.name="ResourceError"}}class _ extends R{constructor(s,r=null){super(s,o.PERMISSION_ERROR,403,r),this.name="PermissionError"}}class C extends R{constructor(s,r=null){super(s,o.FILE_ERROR,500,r),this.name="FileError"}}class L extends R{constructor(s,r=null){super(s,o.PROCESS_ERROR,500,r),this.name="ProcessError"}}function I(e){return l(e)}function a(e){if(!e)return e;if(typeof e=="string")return l(e);if(typeof e=="object"){const s={};for(const[r,n]of Object.entries(e))typeof n=="string"?s[r]=l(n):typeof n=="object"?s[r]=a(n):s[r]=n;return s}return e}function O(e,s=null){const r={success:!1,code:e.code||e.details&&e.details.code||"UNKNOWN_ERROR",error:{type:e.type||o.UNKNOWN_ERROR,message:e.message||"Unknown error",timestamp:e.timestamp||S(),requestId:s}};return process.env.NODE_ENV==="development"?(r.error.stack=I(e.stack),r.error.details=a(e.details)):e.details&&(r.error.details=a(e.details)),r}function A(e,s,r,n){let t=e;const c=s.requestId||"unknown",N=s.body?.projectId||s.query?.projectId||"default";if(!(t instanceof R))if(t.name==="ValidationError")t=new i(t.message,t.details);else if(t.name==="MulterError")if(t.code==="LIMIT_FILE_SIZE"){const U=Math.round(h.UPLOAD_MAX_FILE_SIZE_BYTES/1024/1024*10)/10;t=new i("File size exceeds limit",{maxSize:`${U}MB`})}else t.code==="LIMIT_FILE_COUNT"?t=new i("File count exceeds limit"):t.code==="LIMIT_UNEXPECTED_FILE"?t=new i("File field name error, please use 'file' field to upload file",{expectedField:"file",receivedField:t.field}):t.code==="LIMIT_PART_COUNT"?t=new i("Form field count exceeds limit"):t.code==="LIMIT_FIELD_KEY"?t=new i("Field name length exceeds limit"):t.code==="LIMIT_FIELD_VALUE"?t=new i("Field value length exceeds limit"):t.code==="LIMIT_FIELD_COUNT"?t=new i("Form field count exceeds limit"):t=new i("File upload error: "+t.message,{code:t.code,field:t.field});else t.code==="ENOENT"?t=new d("File or directory not found"):t.code==="EACCES"?t=new _("Permission denied"):t.code==="ECONNREFUSED"?t=new u("Connection refused",{code:t.code}):t=new u(t.message||"Internal server error",{originalError:t.name,code:t.code});const p=t.statusCode>=500?"ERROR":"WARN";f(N,p,`Error handling: ${t.message}`,{requestId:c,errorType:t.type,statusCode:t.statusCode,url:s.originalUrl,method:s.method,userAgent:s.headers["user-agent"],ip:s.ip,stack:t.stack,details:t.details});const T=O(t,c);r.status(t.statusCode).json(T)}function M(e,s,r){const n=new d(`Path not found: ${e.originalUrl}`),t=e.requestId||"unknown";f("default","WARN",`404 error: ${e.originalUrl}`,{requestId:t,method:e.method,ip:e.ip,userAgent:e.headers["user-agent"]});const c=O(n,t);s.status(404).json(c)}function P(e){return(s,r,n)=>{Promise.resolve(e(s,r,n)).catch(n)}}function m(e){return e instanceof R?e.type:e.code==="ENOENT"?o.RESOURCE_ERROR:e.code==="EACCES"?o.PERMISSION_ERROR:e.code==="ECONNREFUSED"?o.NETWORK_ERROR:e.name==="ValidationError"?o.VALIDATION_ERROR:o.UNKNOWN_ERROR}const E={counts:new Map,lastReset:Date.now()};function w(e){const s=m(e),r=E.counts.get(s)||0;E.counts.set(s,r+1)}function x(){return{counts:Object.fromEntries(E.counts),lastReset:E.lastReset,totalErrors:Array.from(E.counts.values()).reduce((e,s)=>e+s,0)}}function y(){E.counts.clear(),E.lastReset=Date.now()}export{o as ERROR_TYPES,R as AppError,i as ValidationError,g as BusinessError,u as SystemError,d as ResourceError,_ as PermissionError,C as FileError,L as ProcessError,O as formatErrorResponse,A as errorHandler,M as notFoundHandler,P as asyncHandler,m as classifyError,l as sanitizeSensitivePaths,I as sanitizeErrorStack,a as sanitizeErrorDetails,w as recordError,x as getErrorStats,y as resetErrorStats};
@@ -1,2 +1,2 @@
1
- import f from"fs";import v from"path";import{getLogDir as L,getCSTDateString as F}from"./logUtils.js";import h from"./logCacheManager.js";import{SystemError as D}from"../error/errorHandler.js";import{sanitizeSensitivePaths as C}from"../common/sensitiveUtils.js";function y(e,t,c,i){try{let s,o=!1,l=!1;const n=L(String(e)),r=v.join(n,t);if(h.isEnabled()){const a=h.get(String(e),r);a&&(s=a.lines,o=!0)}if(!s){const m=f.statSync(r).size,S=f.readFileSync(r,"utf8");s=S.split(`
2
- `),h.isEnabled()&&!h.set(String(e),r,S)&&m>h.maxFileSize&&(l=!0)}const u=s.slice(c).map((a,m)=>({line:i+m,content:C(a)}));return{success:!0,message:o?"\u83B7\u53D6\u65E5\u5FD7\u6210\u529F\uFF08\u7F13\u5B58\uFF09":l?"\u83B7\u53D6\u65E5\u5FD7\u6210\u529F\uFF08\u6587\u4EF6\u8FC7\u5927\uFF0C\u672A\u7F13\u5B58\uFF09":"\u83B7\u53D6\u65E5\u5FD7\u6210\u529F",logs:u,totalLines:s.length,startIndex:i,cacheHit:o,fileTooLarge:l,logFileName:t}}catch(s){throw new D("\u8BFB\u53D6\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25",{projectId:e,logFileName:t,error:s.message})}}async function d(e,t=1){const c=Math.max(0,t-1),i=L(String(e));if(!f.existsSync(i))return{success:!0,message:"\u65E5\u5FD7\u76EE\u5F55\u4E0D\u5B58\u5728",logs:[],totalLines:0,startLine:t};const s=f.readdirSync(i),l=`dev-${F()}.log`,n=s.filter(g=>g===l);if(n.length===0)return{success:!0,message:"\u672A\u627E\u5230\u4E3B\u65E5\u5FD7\u6587\u4EF6",logs:[],totalLines:0,startLine:t};n.sort((g,u)=>{const a=g.match(/dev-(.+)\.log/)?.[1],m=u.match(/dev-(.+)\.log/)?.[1];return!a||!m?0:m.localeCompare(a)});const r=n[0];return y(e,r,c,t)}async function p(e,t=1){const c=Math.max(0,t-1),i=L(String(e));if(!f.existsSync(i))return{success:!0,message:"\u65E5\u5FD7\u76EE\u5F55\u4E0D\u5B58\u5728",logs:[],totalLines:0,startLine:t};const o=f.readdirSync(i).filter(n=>n.startsWith("dev-temp-")&&n.endsWith(".log"));if(o.length===0)return{success:!0,message:"\u672A\u627E\u5230\u4E34\u65F6\u65E5\u5FD7\u6587\u4EF6",logs:[],totalLines:0,startLine:t};o.sort((n,r)=>{const g=n.match(/dev-temp-(\d+)\.log/)?.[1],u=r.match(/dev-temp-(\d+)\.log/)?.[1];return Number(u)-Number(g)});const l=o[0];return y(e,l,c,t)}async function M(e,t=1,c){return c==="main"?await d(e,t):await p(e,t)}export{M as getDevLog,d as getDevLogFromMainLog,p as getDevLogFromTempLog};
1
+ import f from"fs";import v from"path";import{getLogDir as d,getCSTDateString as F}from"./logUtils.js";import h from"./logCacheManager.js";import{SystemError as D}from"../error/errorHandler.js";import{sanitizeSensitivePaths as M}from"../common/sensitiveUtils.js";function y(t,e,l,i){try{let s,n=!1,c=!1;const o=d(String(t)),r=v.join(o,e);if(h.isEnabled()){const a=h.get(String(t),r);a&&(s=a.lines,n=!0)}if(!s){const m=f.statSync(r).size,L=f.readFileSync(r,"utf8");s=L.split(`
2
+ `),h.isEnabled()&&!h.set(String(t),r,L)&&m>h.maxFileSize&&(c=!0)}const u=s.slice(l).map((a,m)=>({line:i+m,content:M(a)}));return{success:!0,message:n?"Get log successfully (cache)":c?"Get log successfully (file too large, not cached)":"Get log successfully",logs:u,totalLines:s.length,startIndex:i,cacheHit:n,fileTooLarge:c,logFileName:e}}catch(s){throw new D("Failed to read log file",{projectId:t,logFileName:e,error:s.message})}}async function S(t,e=1){const l=Math.max(0,e-1),i=d(String(t));if(!f.existsSync(i))return{success:!0,message:"Log directory does not exist",logs:[],totalLines:0,startLine:e};const s=f.readdirSync(i),c=`dev-${F()}.log`,o=s.filter(g=>g===c);if(o.length===0)return{success:!0,message:"Main log file not found",logs:[],totalLines:0,startLine:e};o.sort((g,u)=>{const a=g.match(/dev-(.+)\.log/)?.[1],m=u.match(/dev-(.+)\.log/)?.[1];return!a||!m?0:m.localeCompare(a)});const r=o[0];return y(t,r,l,e)}async function p(t,e=1){const l=Math.max(0,e-1),i=d(String(t));if(!f.existsSync(i))return{success:!0,message:"Log directory does not exist",logs:[],totalLines:0,startLine:e};const n=f.readdirSync(i).filter(o=>o.startsWith("dev-temp-")&&o.endsWith(".log"));if(n.length===0)return{success:!0,message:"Temporary log file not found",logs:[],totalLines:0,startLine:e};n.sort((o,r)=>{const g=o.match(/dev-temp-(\d+)\.log/)?.[1],u=r.match(/dev-temp-(\d+)\.log/)?.[1];return Number(u)-Number(g)});const c=n[0];return y(t,c,l,e)}async function T(t,e=1,l){return l==="main"?await S(t,e):await p(t,e)}export{T as getDevLog,S as getDevLogFromMainLog,p as getDevLogFromTempLog};
@@ -1,2 +1,2 @@
1
- import"fs";import"path";import s from"../../appConfig/index.js";class o{constructor(){this.cache=new Map,this.enabled=s.LOG_CACHE_ENABLED,this.cacheDuration=s.LOG_CACHE_DURATION,this.maxCacheEntries=s.LOG_CACHE_MAX_ENTRIES,this.maxFileSize=s.LOG_CACHE_MAX_FILE_SIZE,this.enabled&&(this.cleanupInterval=setInterval(()=>{this._cleanupExpiredCache()},6e4))}isEnabled(){return this.enabled}get(i,e){if(!this.enabled)return null;const n=String(i),t=this.cache.get(n);if(!t)return null;if(t.filePath!==e)return this.cache.delete(n),null;const a=Date.now();return t.timestamp=a,{lines:t.lines,totalLines:t.totalLines,timestamp:t.timestamp}}set(i,e,n){if(!this.enabled)return!1;const t=Buffer.byteLength(n,"utf8");if(t>this.maxFileSize)return console.log(`\u65E5\u5FD7\u6587\u4EF6\u8FC7\u5927\uFF0C\u4E0D\u7F13\u5B58: ${i}, \u5927\u5C0F: ${(t/1024/1024).toFixed(2)}MB, \u9650\u5236: ${(this.maxFileSize/1024/1024).toFixed(2)}MB`),!1;const a=String(i);if(!this.cache.has(a)&&this.cache.size>=this.maxCacheEntries){const c=this._findOldestCacheKey();c&&this.cache.delete(c)}const l=n.split(`
2
- `);return this.cache.set(a,{lines:l,totalLines:l.length,timestamp:Date.now(),filePath:e}),!0}delete(i){const e=String(i);this.cache.delete(e)}clear(){this.cache.clear()}_cleanupExpiredCache(){const i=Date.now(),e=[];for(const[n,t]of this.cache.entries())i-t.timestamp>this.cacheDuration&&e.push(n);e.forEach(n=>{this.cache.delete(n)}),e.length>0&&console.log(`\u6E05\u7406\u4E86 ${e.length} \u4E2A\u8FC7\u671F\u7684\u65E5\u5FD7\u7F13\u5B58`)}_findOldestCacheKey(){let i=null,e=1/0;for(const[n,t]of this.cache.entries())t.timestamp<e&&(e=t.timestamp,i=n);return i}getStats(){let i=0,e=0;for(const[n,t]of this.cache.entries())if(t.lines&&Array.isArray(t.lines)){let a=0;for(const l of t.lines){const c=Buffer.byteLength(l,"utf8");a+=c,i+=c}a>e&&(e=a)}return{enabled:this.enabled,cacheSize:this.cache.size,maxCacheEntries:this.maxCacheEntries,cacheDuration:this.cacheDuration,maxFileSizeMB:(e/1024/1024).toFixed(2),totalCacheSizeMB:(i/1024/1024).toFixed(2),NODE_ENV:s.NODE_ENV,LOG_CACHE_ENABLED:s.LOG_CACHE_ENABLED}}destroy(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.clear()}}let h=null;function f(){return h||(h=new o,h.enabled&&console.log("\u65E5\u5FD7\u7F13\u5B58\u5DF2\u542F\u7528")),h}const u=new Proxy({},{get(r,i){const e=f(),n=e[i];return typeof n=="function"?n.bind(e):n}});export default u;
1
+ import"fs";import"path";import s from"../../appConfig/index.js";class o{constructor(){this.cache=new Map,this.enabled=s.LOG_CACHE_ENABLED,this.cacheDuration=s.LOG_CACHE_DURATION,this.maxCacheEntries=s.LOG_CACHE_MAX_ENTRIES,this.maxFileSize=s.LOG_CACHE_MAX_FILE_SIZE,this.enabled&&(this.cleanupInterval=setInterval(()=>{this._cleanupExpiredCache()},6e4))}isEnabled(){return this.enabled}get(i,e){if(!this.enabled)return null;const a=String(i),t=this.cache.get(a);if(!t)return null;if(t.filePath!==e)return this.cache.delete(a),null;const n=Date.now();return t.timestamp=n,{lines:t.lines,totalLines:t.totalLines,timestamp:t.timestamp}}set(i,e,a){if(!this.enabled)return!1;const t=Buffer.byteLength(a,"utf8");if(t>this.maxFileSize)return console.log(`Log file too large, not cached: ${i}, size: ${(t/1024/1024).toFixed(2)}MB, limit: ${(this.maxFileSize/1024/1024).toFixed(2)}MB`),!1;const n=String(i);if(!this.cache.has(n)&&this.cache.size>=this.maxCacheEntries){const c=this._findOldestCacheKey();c&&this.cache.delete(c)}const l=a.split(`
2
+ `);return this.cache.set(n,{lines:l,totalLines:l.length,timestamp:Date.now(),filePath:e}),!0}delete(i){const e=String(i);this.cache.delete(e)}clear(){this.cache.clear()}_cleanupExpiredCache(){const i=Date.now(),e=[];for(const[a,t]of this.cache.entries())i-t.timestamp>this.cacheDuration&&e.push(a);e.forEach(a=>{this.cache.delete(a)}),e.length>0&&console.log(`Cleaned ${e.length} expired log caches`)}_findOldestCacheKey(){let i=null,e=1/0;for(const[a,t]of this.cache.entries())t.timestamp<e&&(e=t.timestamp,i=a);return i}getStats(){let i=0,e=0;for(const[a,t]of this.cache.entries())if(t.lines&&Array.isArray(t.lines)){let n=0;for(const l of t.lines){const c=Buffer.byteLength(l,"utf8");n+=c,i+=c}n>e&&(e=n)}return{enabled:this.enabled,cacheSize:this.cache.size,maxCacheEntries:this.maxCacheEntries,cacheDuration:this.cacheDuration,maxFileSizeMB:(e/1024/1024).toFixed(2),totalCacheSizeMB:(i/1024/1024).toFixed(2),NODE_ENV:s.NODE_ENV,LOG_CACHE_ENABLED:s.LOG_CACHE_ENABLED}}destroy(){this.cleanupInterval&&(clearInterval(this.cleanupInterval),this.cleanupInterval=null),this.clear()}}let h=null;function f(){return h||(h=new o,h.enabled&&console.log("Log cache enabled")),h}const u=new Proxy({},{get(r,i){const e=f(),a=e[i];return typeof a=="function"?a.bind(e):a}});export default u;
@@ -1,2 +1,2 @@
1
- import I from"fs";import y from"path";import a from"../../appConfig/index.js";function E(t){const o=a.LOG_BASE_DIR,e=String(t);if(e.startsWith("computer:")){const[,s,n]=e.split(":"),r=a.COMPUTER_LOG_DIR||o;return y.join(r,String(s||"unknown"),String(n||"unknown"))}return y.join(o,e)}function $(){const t=new Date,e=new Intl.DateTimeFormat("zh-CN",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(t),s=e.find(c=>c.type==="year").value,n=e.find(c=>c.type==="month").value,r=e.find(c=>c.type==="day").value,i=e.find(c=>c.type==="hour").value,g=e.find(c=>c.type==="minute").value,u=e.find(c=>c.type==="second").value;return`${s}-${n}-${r} ${i}:${g}:${u}`}function T(){return $().split(" ")[0]}function R(){return $().replace(/-/g,"/")}function C(){return Math.random().toString(36).substr(2,9)}function w(t){return t.ip||t.connection.remoteAddress||t.socket.remoteAddress||(t.connection.socket?t.connection.socket.remoteAddress:null)||t.headers["x-forwarded-for"]?.split(",")[0]||"unknown"}function l(t,o,e={}){const s=R(),n=Object.keys(e).length>0?` ${JSON.stringify(e)}`:"";return`[${s}] [${t.toUpperCase()}] ${o}${n}`}const d={ERROR:0,WARN:1,INFO:2,DEBUG:3},O=function(){switch((a.LOG_LEVEL||"info").toLowerCase()){case"error":return d.ERROR;case"warn":return d.WARN;case"debug":return d.DEBUG;case"info":default:return d.INFO}}();function P(t,o){const e=E(String(t)),s=T();return I.existsSync(e)||I.mkdirSync(e,{recursive:!0}),y.join(e,`${o}-${s}.log`)}const f=new Map;function D(t,o){const e=String(t),s=P(e,o),n=f.get(e);if(n&&n.filePath===s&&!n.stream.destroyed)return n.stream;if(n&&n.stream&&!n.stream.destroyed)try{n.stream.end()}catch{}const r=I.createWriteStream(s,{flags:"a",encoding:"utf8"});return r.on("error",i=>{console.error("API\u65E5\u5FD7\u5199\u5165\u6D41\u9519\u8BEF:",i&&i.message?i.message:i)}),r.on("close",()=>{const i=f.get(e);i&&i.stream===r&&f.delete(e)}),f.set(e,{stream:r,filePath:s}),r}function m(t,o,e,s,n={}){try{const r=l(e,s,n)+`
2
- `;D(String(t),o).write(r)||console.warn(`\u65E5\u5FD7\u5199\u5165\u56DE\u538B: ${t}`)}catch(r){console.error("\u5199\u5165\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:",r.message)}}function p(t,o,e,s={}){const n=String(o).toUpperCase();if(d[n]<=O){a.LOG_CONSOLE_ENABLED&&console.log(l(n,e,s));const r=String(t||"default");m(r,a.LOG_PREFIX_API||"api",n,e,s)}}function A(t,o,e,s={}){const n=String(o).toUpperCase();if(d[n]<=O){a.LOG_CONSOLE_ENABLED&&console.log(l(n,e,s));const r=String(t||"default");m(r,a.LOG_PREFIX_BUILD||"build",n,e,s),m(r,a.LOG_PREFIX_API||"api",n,e,s)}}function k(t,o,e){const s=Date.now(),n=C(),r=w(t);t.requestId=n;const i=`${t.method}-[${t.requestId}] -\u8BF7\u6C42 ${t.originalUrl||t.url} -`,g={requestId:n,clientIP:r,userAgent:t.headers["user-agent"]||"unknown",contentType:t.headers["content-type"]||"unknown"};let u="default";t.method==="GET"?u=t.query.projectId||"default":(t.method==="POST"||t.method==="PUT"||t.method==="PATCH")&&(u=t.body&&t.body.projectId?t.body.projectId:"default"),p(u,"INFO",i,g),o.on("finish",()=>{const h=Date.now()-s,L=o.statusCode>=400?"ERROR":o.statusCode>=300?"WARN":"INFO",S=`${t.method}-[${t.requestId}] -\u54CD\u5E94(${o.statusCode}) ${t.originalUrl||t.url} - `,_={requestId:n,clientIP:r,responseTime:`${h}ms`,contentLength:o.get("content-length")||"unknown",statusCode:o.statusCode};p(u,L,S,_)}),o.on("close",()=>{if(!o.finished){const h=Date.now()-s,L=`${t.method}-[${t.requestId}] -\u54CD\u5E94(${o.statusCode}) ${t.originalUrl||t.url} - Connection closed`,S={requestId:n,clientIP:r,responseTime:`${h}ms`,contentLength:o.get("content-length")||"unknown",statusCode:o.statusCode};p(u,"ERROR",L,S)}}),e()}export{p as log,A as logBuild,k as logger,E as getLogDir,C as generateRequestId,w as getClientIP,l as formatLogMessage,P as getLogFilePath,m as writeToLogFile,$ as getCSTDateTimeString,T as getCSTDateString,R as getCSTTimestampString,d as LOG_LEVELS,O as CURRENT_LOG_LEVEL};
1
+ import I from"fs";import y from"path";import a from"../../appConfig/index.js";function O(t){const o=a.LOG_BASE_DIR,e=String(t);if(e.startsWith("computer:")){const[,s,n]=e.split(":"),r=a.COMPUTER_LOG_DIR||o;return y.join(r,String(s||"unknown"),String(n||"unknown"))}return y.join(o,e)}function R(){const t=new Date,e=new Intl.DateTimeFormat("zh-CN",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(t),s=e.find(c=>c.type==="year").value,n=e.find(c=>c.type==="month").value,r=e.find(c=>c.type==="day").value,i=e.find(c=>c.type==="hour").value,g=e.find(c=>c.type==="minute").value,u=e.find(c=>c.type==="second").value;return`${s}-${n}-${r} ${i}:${g}:${u}`}function E(){return R().split(" ")[0]}function T(){return R().replace(/-/g,"/")}function C(){return Math.random().toString(36).substr(2,9)}function w(t){return t.ip||t.connection.remoteAddress||t.socket.remoteAddress||(t.connection.socket?t.connection.socket.remoteAddress:null)||t.headers["x-forwarded-for"]?.split(",")[0]||"unknown"}function l(t,o,e={}){const s=T(),n=Object.keys(e).length>0?` ${JSON.stringify(e)}`:"";return`[${s}] [${t.toUpperCase()}] ${o}${n}`}const d={ERROR:0,WARN:1,INFO:2,DEBUG:3},$=function(){switch((a.LOG_LEVEL||"info").toLowerCase()){case"error":return d.ERROR;case"warn":return d.WARN;case"debug":return d.DEBUG;case"info":default:return d.INFO}}();function P(t,o){const e=O(String(t)),s=E();return I.existsSync(e)||I.mkdirSync(e,{recursive:!0}),y.join(e,`${o}-${s}.log`)}const f=new Map;function D(t,o){const e=String(t),s=P(e,o),n=f.get(e);if(n&&n.filePath===s&&!n.stream.destroyed)return n.stream;if(n&&n.stream&&!n.stream.destroyed)try{n.stream.end()}catch{}const r=I.createWriteStream(s,{flags:"a",encoding:"utf8"});return r.on("error",i=>{console.error("API\u65E5\u5FD7\u5199\u5165\u6D41\u9519\u8BEF:",i&&i.message?i.message:i)}),r.on("close",()=>{const i=f.get(e);i&&i.stream===r&&f.delete(e)}),f.set(e,{stream:r,filePath:s}),r}function m(t,o,e,s,n={}){try{const r=l(e,s,n)+`
2
+ `;D(String(t),o).write(r)||console.warn(`\u65E5\u5FD7\u5199\u5165\u56DE\u538B: ${t}`)}catch(r){console.error("\u5199\u5165\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:",r.message)}}function p(t,o,e,s={}){const n=String(o).toUpperCase();if(d[n]<=$){a.LOG_CONSOLE_ENABLED&&console.log(l(n,e,s));const r=String(t||"default");m(r,a.LOG_PREFIX_API||"api",n,e,s)}}function A(t,o,e,s={}){const n=String(o).toUpperCase();if(d[n]<=$){a.LOG_CONSOLE_ENABLED&&console.log(l(n,e,s));const r=String(t||"default");m(r,a.LOG_PREFIX_BUILD||"build",n,e,s),m(r,a.LOG_PREFIX_API||"api",n,e,s)}}function k(t,o,e){const s=Date.now(),n=C(),r=w(t);t.requestId=n;const i=`${t.method}-[${t.requestId}] -Request ${t.originalUrl||t.url} -`,g={requestId:n,clientIP:r,userAgent:t.headers["user-agent"]||"unknown",contentType:t.headers["content-type"]||"unknown"};let u="default";t.method==="GET"?u=t.query.projectId||"default":(t.method==="POST"||t.method==="PUT"||t.method==="PATCH")&&(u=t.body&&t.body.projectId?t.body.projectId:"default"),p(u,"INFO",i,g),o.on("finish",()=>{const h=Date.now()-s,L=o.statusCode>=400?"ERROR":o.statusCode>=300?"WARN":"INFO",S=`${t.method}-[${t.requestId}] -Response(${o.statusCode}) ${t.originalUrl||t.url} - `,_={requestId:n,clientIP:r,responseTime:`${h}ms`,contentLength:o.get("content-length")||"unknown",statusCode:o.statusCode};p(u,L,S,_)}),o.on("close",()=>{if(!o.finished){const h=Date.now()-s,L=`${t.method}-[${t.requestId}] -Response(${o.statusCode}) ${t.originalUrl||t.url} - Connection closed`,S={requestId:n,clientIP:r,responseTime:`${h}ms`,contentLength:o.get("content-length")||"unknown",statusCode:o.statusCode};p(u,"ERROR",L,S)}}),e()}export{p as log,A as logBuild,k as logger,O as getLogDir,C as generateRequestId,w as getClientIP,l as formatLogMessage,P as getLogFilePath,m as writeToLogFile,R as getCSTDateTimeString,E as getCSTDateString,T as getCSTTimestampString,d as LOG_LEVELS,$ as CURRENT_LOG_LEVEL};
@@ -1 +1 @@
1
- import t from"fs";import m from"path";import A from"archiver";import C from"yauzl";import d from"../../appConfig/index.js";import{log as S}from"../log/logUtils.js";import{FileError as g}from"../error/errorHandler.js";import{sanitizeSensitivePaths as _}from"../common/sensitiveUtils.js";async function T(e,r){const n=new Set(d.TRAVERSE_EXCLUDE_DIRS||[]),u=new Set(d.BACKUP_TRAVERSE_EXCLUDE_FILES||[]),c=await t.promises.readdir(e,{withFileTypes:!0});for(const o of c){const f=m.join(e,o.name),i=m.join(r,o.name);if(o.isDirectory()){if(n.has(o.name))continue;await t.promises.mkdir(i,{recursive:!0}),await T(f,i)}else if(o.isFile()){if(u.has(o.name))continue;await t.promises.mkdir(m.dirname(i),{recursive:!0}),await t.promises.copyFile(f,i)}}}async function L(e,r,n){const u=Date.now(),c=m.join(d.UPLOAD_PROJECT_DIR,e);t.existsSync(c)||t.mkdirSync(c,{recursive:!0});const o=m.join(c,`backup_temp_${Date.now()}`);await t.promises.mkdir(o,{recursive:!0});try{return S(e,"DEBUG","\u5F00\u59CB\u590D\u5236\u9879\u76EE\u6587\u4EF6\u5230\u4E34\u65F6\u76EE\u5F55",{projectPath:r,tempDir:o}),await T(r,o),S(e,"DEBUG","\u9879\u76EE\u6587\u4EF6\u590D\u5236\u5B8C\u6210\uFF0C\u5F00\u59CB\u538B\u7F29",{tempDir:o,outZipPath:n}),await t.promises.mkdir(m.dirname(n),{recursive:!0}),await new Promise((f,i)=>{const a=t.createWriteStream(n),l=A("zip",{zlib:{level:9}});a.on("close",()=>f()),a.on("error",s=>i(new g("\u5907\u4EFDzip\u538B\u7F29\u5931\u8D25",{projectId:e,projectPath:r,outZipPath:n,originalError:s&&s.message}))),l.on("warning",s=>{s&&s.code==="ENOENT"?S(e,"WARN",`\u538B\u7F29\u544A\u8B66: ${s.message}`,{projectId:e,outZipPath:n}):s&&i(new g("\u5907\u4EFDzip\u538B\u7F29\u5931\u8D25",{projectId:e,projectPath:r,outZipPath:n,originalError:s&&s.message}))}),l.on("error",s=>i(new g("\u5907\u4EFDzip\u538B\u7F29\u5931\u8D25",{projectId:e,projectPath:r,outZipPath:n,originalError:s&&s.message}))),l.pipe(a),l.directory(o+"/",!1),l.finalize()}),S(e,"INFO",`\u9879\u76EE\u5DF2\u5907\u4EFD: ${n}`,{projectId:e,outZipPath:n,elapsedMs:Date.now()-u}),n}finally{try{await t.promises.rm(o,{recursive:!0,force:!0})}catch{}}}async function x(e,r,n){const u=Date.now(),c=new Set(d.TRAVERSE_EXCLUDE_DIRS||[]),o=new Set(d.BACKUP_TRAVERSE_EXCLUDE_FILES||[]);S(e,"DEBUG","\u5F00\u59CB\u6E05\u7A7A\u9879\u76EE\u76EE\u5F55\uFF08\u4FDD\u7559\u6392\u9664\u9879\uFF09",{projectPath:r});const f=await t.promises.readdir(r,{withFileTypes:!0});for(const i of f){const a=m.join(r,i.name);if(!(i.isDirectory()&&c.has(i.name))&&!(i.isFile()&&o.has(i.name)))try{await t.promises.rm(a,{recursive:!0,force:!0})}catch{}}S(e,"DEBUG","\u5F00\u59CB\u4ECE zip \u6062\u590D\u9879\u76EE\u6587\u4EF6",{zipPath:n,projectPath:r}),await new Promise((i,a)=>{C.open(n,{lazyEntries:!0},(l,s)=>{if(l||!s)return a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:l&&l.message}));const R=m.resolve(r);s.readEntry(),s.on("entry",w=>{const U=m.normalize(w.fileName).replace(/^([/\\]+)+/,""),k=m.join(r,U),v=m.resolve(k);if(!v.startsWith(R+m.sep)&&v!==R){s.readEntry();return}if(/\\$|\/$/.test(w.fileName)||w.fileName.endsWith("/")){t.promises.mkdir(v,{recursive:!0}).then(()=>s.readEntry()).catch(E=>{s.close(),a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:E&&E.message?_(E.message):E&&E.message}))});return}s.openReadStream(w,(E,N)=>{if(E||!N)return s.close(),a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:E&&E.message}));t.promises.mkdir(m.dirname(v),{recursive:!0}).then(()=>{const y=t.createWriteStream(v);N.pipe(y),y.on("close",()=>s.readEntry()),y.on("error",D=>{s.close(),a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:D&&D.message?_(D.message):D&&D.message}))})}).catch(y=>{s.close(),a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:y&&y.message?_(y.message):y&&y.message}))})})}),s.on("end",()=>{s.close(),i()}),s.on("error",w=>{s.close(),a(new g("\u56DE\u6EDA\u89E3\u538B\u5931\u8D25",{projectId:e,projectPath:r,zipPath:n,originalError:w&&w.message?_(w.message):w&&w.message}))})})}),S(e,"INFO",`\u9879\u76EE\u5DF2\u4ECE\u5907\u4EFD\u6062\u590D: ${n}`,{projectId:e,projectPath:r,zipPath:n,elapsedMs:Date.now()-u})}async function B(e,r,n){const u=new Set(n||[]),c=new Set((d.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).map(f=>String(f).trim()));async function o(f){const i=await t.promises.readdir(f,{withFileTypes:!0});for(const a of i){const l=m.join(f,a.name),s=m.relative(e,l);if(a.isDirectory()){if(u.has(a.name))continue;await o(l)}else if(a.isFile()){if(a.name.startsWith(".")||c.has(a.name))continue;if(!r.has(s))try{await t.promises.unlink(l)}catch{}}}}await o(e)}async function O(e,r){const n=new Set(r||[]);async function u(c){const o=await t.promises.readdir(c,{withFileTypes:!0});for(const i of o){const a=m.join(c,i.name);if(i.isDirectory()){if(n.has(i.name))continue;await u(a)}}if((await t.promises.readdir(c)).length===0&&m.resolve(c)!==m.resolve(e))try{await t.promises.rmdir(c)}catch{}}await u(e)}export{T as copyDirectoryFiltered,L as backupProjectToZip,x as restoreProjectFromZip,B as pruneMissingFiles,O as removeEmptyDirectories};
1
+ import t from"fs";import m from"path";import U from"archiver";import A from"yauzl";import S from"../../appConfig/index.js";import{log as d}from"../log/logUtils.js";import{FileError as y}from"../error/errorHandler.js";import{sanitizeSensitivePaths as D}from"../common/sensitiveUtils.js";async function _(e,r){const i=new Set(S.TRAVERSE_EXCLUDE_DIRS||[]),u=new Set(S.BACKUP_TRAVERSE_EXCLUDE_FILES||[]),c=await t.promises.readdir(e,{withFileTypes:!0});for(const a of c){const f=m.join(e,a.name),n=m.join(r,a.name);if(a.isDirectory()){if(i.has(a.name))continue;await t.promises.mkdir(n,{recursive:!0}),await _(f,n)}else if(a.isFile()){if(u.has(a.name))continue;await t.promises.mkdir(m.dirname(n),{recursive:!0}),await t.promises.copyFile(f,n)}}}async function B(e,r,i){const u=Date.now(),c=m.join(S.UPLOAD_PROJECT_DIR,e);t.existsSync(c)||t.mkdirSync(c,{recursive:!0});const a=m.join(c,`backup_temp_${Date.now()}`);await t.promises.mkdir(a,{recursive:!0});try{return d(e,"DEBUG","Start copying project files to temporary directory",{projectPath:r,tempDir:a}),await _(r,a),d(e,"DEBUG","Project files copied, start compressing",{tempDir:a,outZipPath:i}),await t.promises.mkdir(m.dirname(i),{recursive:!0}),await new Promise((f,n)=>{const o=t.createWriteStream(i),l=U("zip",{zlib:{level:9}});o.on("close",()=>f()),o.on("error",s=>n(new y("Backup zip compression failed",{projectId:e,projectPath:r,outZipPath:i,originalError:s&&s.message}))),l.on("warning",s=>{s&&s.code==="ENOENT"?d(e,"WARN",`Compression warning: ${s.message}`,{projectId:e,outZipPath:i}):s&&n(new y("Backup zip compression failed",{projectId:e,projectPath:r,outZipPath:i,originalError:s&&s.message}))}),l.on("error",s=>n(new y("Backup zip compression failed",{projectId:e,projectPath:r,outZipPath:i,originalError:s&&s.message}))),l.pipe(o),l.directory(a+"/",!1),l.finalize()}),d(e,"INFO",`Project backup completed: ${i}`,{projectId:e,outZipPath:i,elapsedMs:Date.now()-u}),i}finally{try{await t.promises.rm(a,{recursive:!0,force:!0})}catch{}}}async function C(e,r,i){const u=Date.now(),c=new Set(S.TRAVERSE_EXCLUDE_DIRS||[]),a=new Set(S.BACKUP_TRAVERSE_EXCLUDE_FILES||[]);d(e,"DEBUG","Start clearing project directory (keep excluded items)",{projectPath:r});const f=await t.promises.readdir(r,{withFileTypes:!0});for(const n of f){const o=m.join(r,n.name);if(!(n.isDirectory()&&c.has(n.name))&&!(n.isFile()&&a.has(n.name)))try{await t.promises.rm(o,{recursive:!0,force:!0})}catch{}}d(e,"DEBUG","Start restoring project files from zip",{zipPath:i,projectPath:r}),await new Promise((n,o)=>{A.open(i,{lazyEntries:!0},(l,s)=>{if(l||!s)return o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:l&&l.message}));const R=m.resolve(r);s.readEntry(),s.on("entry",w=>{const p=m.normalize(w.fileName).replace(/^([/\\]+)+/,""),N=m.join(r,p),k=m.resolve(N);if(!k.startsWith(R+m.sep)&&k!==R){s.readEntry();return}if(/\\$|\/$/.test(w.fileName)||w.fileName.endsWith("/")){t.promises.mkdir(k,{recursive:!0}).then(()=>s.readEntry()).catch(E=>{s.close(),o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:E&&E.message?D(E.message):E&&E.message}))});return}s.openReadStream(w,(E,T)=>{if(E||!T)return s.close(),o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:E&&E.message}));t.promises.mkdir(m.dirname(k),{recursive:!0}).then(()=>{const g=t.createWriteStream(k);T.pipe(g),g.on("close",()=>s.readEntry()),g.on("error",v=>{s.close(),o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:v&&v.message?D(v.message):v&&v.message}))})}).catch(g=>{s.close(),o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:g&&g.message?D(g.message):g&&g.message}))})})}),s.on("end",()=>{s.close(),n()}),s.on("error",w=>{s.close(),o(new y("Rollback unzip failed",{projectId:e,projectPath:r,zipPath:i,originalError:w&&w.message?D(w.message):w&&w.message}))})})}),d(e,"INFO",`Project restored from backup: ${i}`,{projectId:e,projectPath:r,zipPath:i,elapsedMs:Date.now()-u})}async function b(e,r,i){const u=new Set(i||[]),c=new Set((S.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).map(f=>String(f).trim()));async function a(f){const n=await t.promises.readdir(f,{withFileTypes:!0});for(const o of n){const l=m.join(f,o.name),s=m.relative(e,l);if(o.isDirectory()){if(u.has(o.name))continue;await a(l)}else if(o.isFile()){if(o.name.startsWith(".")||c.has(o.name))continue;if(!r.has(s))try{await t.promises.unlink(l)}catch{}}}}await a(e)}async function x(e,r){const i=new Set(r||[]);async function u(c){const a=await t.promises.readdir(c,{withFileTypes:!0});for(const n of a){const o=m.join(c,n.name);if(n.isDirectory()){if(i.has(n.name))continue;await u(o)}}if((await t.promises.readdir(c)).length===0&&m.resolve(c)!==m.resolve(e))try{await t.promises.rmdir(c)}catch{}}await u(e)}export{_ as copyDirectoryFiltered,B as backupProjectToZip,C as restoreProjectFromZip,b as pruneMissingFiles,x as removeEmptyDirectories};
@@ -1 +1 @@
1
- import n from"fs";import a from"path";import $ from"../../appConfig/index.js";import{log as f}from"../log/logUtils.js";import{copyDirectoryFiltered as E}from"./backupUtils.js";import{ValidationError as h,BusinessError as l,SystemError as u}from"../error/errorHandler.js";import{createPnpmNpmrc as O}from"../common/npmrcUtils.js";async function R(s,i){if(!s)throw new h("\u6E90\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A",{field:"sourceProjectId"});if(!i)throw new h("\u76EE\u6807\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A",{field:"targetProjectId"});const w=$.PROJECT_SOURCE_DIR,p=a.join(w,s),r=a.join(w,i);if(!n.existsSync(p))throw new l(`\u6E90\u9879\u76EE ${s} \u4E0D\u5B58\u5728`,{sourceProjectId:s,sourceProjectPath:p});if(n.existsSync(r))throw new l(`\u76EE\u6807\u9879\u76EE ${i} \u5DF2\u5B58\u5728`,{targetProjectId:i,targetProjectPath:r});try{f(i,"INFO",`\u5F00\u59CB\u590D\u5236\u9879\u76EE\u4ECE ${s} \u5230 ${i}`,{sourceProjectId:s,targetProjectId:i}),n.mkdirSync(r,{recursive:!0}),f(i,"INFO",`\u76EE\u6807\u9879\u76EE\u76EE\u5F55\u521B\u5EFA\u6210\u529F: ${r}`,{targetProjectId:i});const m=await n.promises.readdir(p,{withFileTypes:!0});for(const o of m){const y=a.join(p,o.name),e=a.join(r,o.name);o.isDirectory()?(await n.promises.mkdir(e,{recursive:!0}),await E(y,e)):o.isFile()&&(await n.promises.mkdir(a.dirname(e),{recursive:!0}),await n.promises.copyFile(y,e))}return f(i,"INFO",`\u9879\u76EE\u590D\u5236\u6210\u529F: ${i}`,{sourceProjectId:s,targetProjectId:i}),await O(r,i),{success:!0,message:`\u9879\u76EE ${s} \u5DF2\u6210\u529F\u590D\u5236\u5230 ${i}`,sourceProjectId:s,targetProjectId:i,targetProjectPath:r}}catch(m){if(f(i,"ERROR",`\u590D\u5236\u9879\u76EE\u5931\u8D25: ${m.message}`,{sourceProjectId:s,targetProjectId:i}),n.existsSync(r))try{await n.promises.rm(r,{recursive:!0,force:!0}),f(i,"INFO","\u590D\u5236\u5931\u8D25\uFF0C\u76EE\u6807\u9879\u76EE\u76EE\u5F55\u5DF2\u6E05\u7406",{targetProjectId:i})}catch(o){f(i,"ERROR",`\u6E05\u7406\u76EE\u6807\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${o.message}`,{targetProjectId:i,originalError:o.message})}throw m.isOperational?m:new u(`\u590D\u5236\u9879\u76EE\u5931\u8D25: ${m.message}`,{sourceProjectId:s,targetProjectId:i,sourceProjectPath:p,targetProjectPath:r,originalError:m.message})}}export{R as copyProject};
1
+ import s from"fs";import m from"path";import w from"../../appConfig/index.js";import{log as p}from"../log/logUtils.js";import{copyDirectoryFiltered as u}from"./backupUtils.js";import{ValidationError as y,BusinessError as l,SystemError as h}from"../error/errorHandler.js";import{createPnpmNpmrc as $}from"../common/npmrcUtils.js";async function E(r,i){if(!r)throw new y("Source project ID cannot be empty",{field:"sourceProjectId"});if(!i)throw new y("Target project ID cannot be empty",{field:"targetProjectId"});const f=w.PROJECT_SOURCE_DIR,a=m.join(f,r),e=m.join(f,i);if(!s.existsSync(a))throw new l(`Source project ${r} does not exist`,{sourceProjectId:r,sourceProjectPath:a});if(s.existsSync(e))throw new l(`Target project ${i} already exists`,{targetProjectId:i,targetProjectPath:e});try{p(i,"INFO",`Start copying project from ${r} to ${i}`,{sourceProjectId:r,targetProjectId:i}),s.mkdirSync(e,{recursive:!0}),p(i,"INFO",`Target project directory created successfully: ${e}`,{targetProjectId:i});const o=await s.promises.readdir(a,{withFileTypes:!0});for(const n of o){const t=m.join(a,n.name),c=m.join(e,n.name);n.isDirectory()?(await s.promises.mkdir(c,{recursive:!0}),await u(t,c)):n.isFile()&&(await s.promises.mkdir(m.dirname(c),{recursive:!0}),await s.promises.copyFile(t,c))}return p(i,"INFO",`Project copied successfully: ${i}`,{sourceProjectId:r,targetProjectId:i}),await $(e,i),{success:!0,message:`Project ${r} successfully copied to ${i}`,sourceProjectId:r,targetProjectId:i,targetProjectPath:e}}catch(o){if(p(i,"ERROR",`Copy project failed: ${o.message}`,{sourceProjectId:r,targetProjectId:i}),s.existsSync(e))try{await s.promises.rm(e,{recursive:!0,force:!0}),p(i,"INFO","Copy failed, target project directory cleaned",{targetProjectId:i})}catch(n){p(i,"ERROR",`Clean target project directory failed: ${n.message}`,{targetProjectId:i,originalError:n.message})}throw o.isOperational?o:new h(`Copy project failed: ${o.message}`,{sourceProjectId:r,targetProjectId:i,sourceProjectPath:a,targetProjectPath:e,originalError:o.message})}}export{E as copyProject};
@@ -1 +1 @@
1
- import o from"fs";import i from"path";import{log as s}from"../log/logUtils.js";function f(n){try{const e=i.join(n,"package.json");if(o.existsSync(e)){const r=JSON.parse(o.readFileSync(e,"utf-8")),t={...r.dependencies,...r.devDependencies};if(t.react||t["react-dom"])return"react";if(t.vue||t["vue-router"]||t["@vue/cli-service"])return"vue"}return"other"}catch(e){return s(null,"WARN",`\u68C0\u6D4B\u524D\u7AEF\u6846\u67B6\u5931\u8D25: ${e.message}`,{projectPath:n,error:e.message}),"other"}}function a(n){try{const e=["next.config.js","next.config.ts","next.config.mjs","next.config.cjs"];for(const t of e){const c=i.join(n,t);if(o.existsSync(c))return"nextjs"}const r=["vite.config.js","vite.config.ts","vite.config.mjs","vite.config.cjs"];for(const t of r){const c=i.join(n,t);if(o.existsSync(c))return"vite"}return"other"}catch(e){return s(null,"WARN",`\u68C0\u6D4B\u5F00\u53D1\u6846\u67B6\u5931\u8D25: ${e.message}`,{projectPath:n,error:e.message}),"other"}}function g(n){const e=f(n),r=a(n);return{frontendFramework:e,devFramework:r}}export{f as detectFrontendFramework,a as detectDevFramework,g as getFrameworkInfo};
1
+ import o from"fs";import i from"path";import{log as s}from"../log/logUtils.js";function f(n){try{const e=i.join(n,"package.json");if(o.existsSync(e)){const r=JSON.parse(o.readFileSync(e,"utf-8")),t={...r.dependencies,...r.devDependencies};if(t.react||t["react-dom"])return"react";if(t.vue||t["vue-router"]||t["@vue/cli-service"])return"vue"}return"other"}catch(e){return s(null,"WARN",`Detect frontend framework failed: ${e.message}`,{projectPath:n,error:e.message}),"other"}}function a(n){try{const e=["next.config.js","next.config.ts","next.config.mjs","next.config.cjs"];for(const t of e){const c=i.join(n,t);if(o.existsSync(c))return"nextjs"}const r=["vite.config.js","vite.config.ts","vite.config.mjs","vite.config.cjs"];for(const t of r){const c=i.join(n,t);if(o.existsSync(c))return"vite"}return"other"}catch(e){return s(null,"WARN",`Detect development framework failed: ${e.message}`,{projectPath:n,error:e.message}),"other"}}function g(n){const e=f(n),r=a(n);return{frontendFramework:e,devFramework:r}}export{f as detectFrontendFramework,a as detectDevFramework,g as getFrameworkInfo};
@@ -1 +1 @@
1
- import u from"fs";import m from"path";import g from"../../appConfig/index.js";import{log as c}from"../log/logUtils.js";import{ValidationError as $,SystemError as h,ResourceError as x}from"../error/errorHandler.js";import{extractZip as N}from"../common/zipUtils.js";import{getFrameworkInfo as O}from"./frameworkDetectorUtils.js";async function _(e){try{const o=u.readFileSync(e);if(o.includes(0))return!0;const f=o.toString("utf-8");for(let l=0;l<f.length;l++){const n=f.charCodeAt(l);if(n<32&&n!==9&&n!==10&&n!==13)return!0}return!1}catch{return!1}}function C(e){const o=m.extname(e).toLowerCase();return[".jpg",".jpeg",".png",".gif",".bmp",".webp",".svg"].includes(o)}async function D(e,o,f,l){const n=[],i=await u.promises.readdir(e,{withFileTypes:!0});i.sort((s,r)=>s.isDirectory()&&!r.isDirectory()?-1:!s.isDirectory()&&r.isDirectory()?1:s.name.toLowerCase().localeCompare(r.name.toLowerCase()));for(const s of i){const r=m.join(e,s.name);if(!(s.name.startsWith(".")||(g.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).includes(s.name))&&!(s.isDirectory()&&g.TRAVERSE_EXCLUDE_DIRS.includes(s.name)))if(s.isDirectory()){const a=await D(r,o,f,l);n.push(...a)}else try{const a=await u.promises.stat(r),w=o||m.join(g.PROJECT_SOURCE_DIR,f),E=m.relative(w,r),F=await _(r),R=`${l}/${E}`,y={name:E,binary:F,sizeExceeded:a.size>g.MAX_INLINE_FILE_SIZE_BYTES,contents:"",fileProxyUrl:R};if(!y.sizeExceeded)if(y.binary){if(C(r)){const S=u.readFileSync(r);y.contents=S.toString("base64")}}else y.contents=u.readFileSync(r,"utf-8");n.push(y)}catch(a){c(f,"WARN",`\u5904\u7406\u6587\u4EF6\u5931\u8D25: ${r} - ${a.message}`,{filePath:r,error:a.message})}}return n}async function U(e,o,f){const l=Date.now(),n=m.basename(e);try{c(n,"INFO","\u5F00\u59CB\u83B7\u53D6\u9879\u76EE\u5185\u5BB9",{projectPath:e,command:o}),c(n,"DEBUG","\u5F00\u59CB\u904D\u5386\u9879\u76EE\u76EE\u5F55",{projectPath:e});const i=await D(e,null,n,f);c(n,"DEBUG","\u9879\u76EE\u76EE\u5F55\u904D\u5386\u5B8C\u6210",{projectPath:e,fileCount:i.length});let s=i;o!=="cpage_config"&&(s=i.filter(a=>a.name!=="cpage_config.json")),c(n,"DEBUG","\u5F00\u59CB\u68C0\u6D4B\u6846\u67B6\u4FE1\u606F",{projectPath:e});const r=O(e),t={files:s,...r};return c(n,"INFO",`\u9879\u76EE\u5185\u5BB9\u83B7\u53D6\u5B8C\u6210\uFF0C\u5171${s.length}\u4E2A\u6587\u4EF6`,{projectPath:e,fileCount:s.length,command:o,elapsedMs:Date.now()-l}),t}catch(i){throw c(n,"ERROR",`\u83B7\u53D6\u9879\u76EE\u5185\u5BB9\u5931\u8D25: ${i.message}`,{projectPath:e,originalError:i.message,elapsedMs:Date.now()-l}),new h(`\u83B7\u53D6\u9879\u76EE\u5185\u5BB9\u5931\u8D25: ${i.message}`,{projectPath:e,originalError:i.message})}}async function T(e,o,f,l){const n=Date.now(),i=Number(o);if(!Number.isFinite(i))throw new $("\u4EE3\u7801\u7248\u672C\u5FC5\u987B\u662F\u6570\u5B57",{field:"codeVersion"});const s=m.join(g.UPLOAD_PROJECT_DIR,e),r=m.join(s,`${e}-v${i}.zip`);if(!u.existsSync(r))throw new x(`\u7248\u672C ${i} \u7684\u5907\u4EFD\u6587\u4EF6\u4E0D\u5B58\u5728`,{projectId:e,codeVersion:i,backupZipPath:r});const t=m.join(g.PROJECT_SOURCE_DIR,"_his",e);try{u.existsSync(t)&&await u.promises.rm(t,{recursive:!0,force:!0}),await u.promises.mkdir(t,{recursive:!0}),c(e,"INFO",`\u5F00\u59CB\u89E3\u538B\u7248\u672C ${i} \u7684\u5907\u4EFD\u6587\u4EF6`,{projectId:e,codeVersion:i,backupZipPath:r,tempExtractDir:t}),c(e,"DEBUG","\u5F00\u59CB\u89E3\u538B\u7248\u672C\u5907\u4EFD\u6587\u4EF6",{projectId:e,backupZipPath:r,tempExtractDir:t}),await N(r,t),c(e,"DEBUG",`\u7248\u672C ${i} \u5907\u4EFD\u6587\u4EF6\u89E3\u538B\u5B8C\u6210`,{projectId:e,codeVersion:i,tempExtractDir:t}),c(e,"DEBUG","\u5F00\u59CB\u904D\u5386\u7248\u672C\u76EE\u5F55",{projectId:e,tempExtractDir:t});const a=await D(t,t,e,l);let w=a;f!=="cpage_config"&&(w=a.filter(F=>F.name!=="cpage_config.json"));const E={files:w};return c(e,"INFO",`\u7248\u672C ${i} \u9879\u76EE\u5185\u5BB9\u83B7\u53D6\u5B8C\u6210`,{projectId:e,codeVersion:i,fileCount:E.files?E.files.length:0,command:f,elapsedMs:Date.now()-n}),E}finally{try{u.existsSync(t)&&(await u.promises.rm(t,{recursive:!0,force:!0}),c(e,"INFO",`\u4E34\u65F6\u76EE\u5F55\u5DF2\u6E05\u7406: ${t}`,{projectId:e,codeVersion:i}))}catch(a){c(e,"WARN",`\u6E05\u7406\u4E34\u65F6\u76EE\u5F55\u5931\u8D25: ${a.message}`,{projectId:e,codeVersion:i,tempExtractDir:t,error:a.message})}}}export{U as getProjectContent,T as getProjectContentByVersion,D as traverseDirectory,_ as isBinaryFile,C as isImageFile};
1
+ import u from"fs";import m from"path";import y from"../../appConfig/index.js";import{log as c}from"../log/logUtils.js";import{ValidationError as _,SystemError as R,ResourceError as x}from"../error/errorHandler.js";import{extractZip as b}from"../common/zipUtils.js";import{getFrameworkInfo as v}from"./frameworkDetectorUtils.js";async function S(e){try{const s=u.readFileSync(e);if(s.includes(0))return!0;const f=s.toString("utf-8");for(let l=0;l<f.length;l++){const i=f.charCodeAt(l);if(i<32&&i!==9&&i!==10&&i!==13)return!0}return!1}catch{return!1}}function p(e){const s=m.extname(e).toLowerCase();return[".jpg",".jpeg",".png",".gif",".bmp",".webp",".svg"].includes(s)}async function d(e,s,f,l){const i=[],r=await u.promises.readdir(e,{withFileTypes:!0});r.sort((n,t)=>n.isDirectory()&&!t.isDirectory()?-1:!n.isDirectory()&&t.isDirectory()?1:n.name.toLowerCase().localeCompare(t.name.toLowerCase()));for(const n of r){const t=m.join(e,n.name);if(!(n.name.startsWith(".")||(y.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).includes(n.name))&&!(n.isDirectory()&&y.TRAVERSE_EXCLUDE_DIRS.includes(n.name)))if(n.isDirectory()){const a=await d(t,s,f,l);i.push(...a)}else try{const a=await u.promises.stat(t),w=s||m.join(y.PROJECT_SOURCE_DIR,f),g=m.relative(w,t),D=await S(t),C=`${l}/${g}`,E={name:g,binary:D,sizeExceeded:a.size>y.MAX_INLINE_FILE_SIZE_BYTES,contents:"",fileProxyUrl:C};if(!E.sizeExceeded)if(E.binary){if(p(t)){const F=u.readFileSync(t);E.contents=F.toString("base64")}}else E.contents=u.readFileSync(t,"utf-8");i.push(E)}catch(a){c(f,"WARN",`Process file failed: ${t} - ${a.message}`,{filePath:t,error:a.message})}}return i}async function $(e,s,f){const l=Date.now(),i=m.basename(e);try{c(i,"INFO","Start getting project content",{projectPath:e,command:s}),c(i,"DEBUG","Start traversing project directory",{projectPath:e});const r=await d(e,null,i,f);c(i,"DEBUG","Project directory traversal completed",{projectPath:e,fileCount:r.length});let n=r;s!=="cpage_config"&&(n=r.filter(a=>a.name!=="cpage_config.json")),c(i,"DEBUG","Start detecting framework information",{projectPath:e});const t=v(e),o={files:n,...t};return c(i,"INFO",`Project content obtained, total ${n.length} files`,{projectPath:e,fileCount:n.length,command:s,elapsedMs:Date.now()-l}),o}catch(r){throw c(i,"ERROR",`Get project content failed: ${r.message}`,{projectPath:e,originalError:r.message,elapsedMs:Date.now()-l}),new R(`Get project content failed: ${r.message}`,{projectPath:e,originalError:r.message})}}async function h(e,s,f,l){const i=Date.now(),r=Number(s);if(!Number.isFinite(r))throw new _("Code version must be a number",{field:"codeVersion"});const n=m.join(y.UPLOAD_PROJECT_DIR,e),t=m.join(n,`${e}-v${r}.zip`);if(!u.existsSync(t))throw new x(`Backup file for version ${r} does not exist`,{projectId:e,codeVersion:r,backupZipPath:t});const o=m.join(y.PROJECT_SOURCE_DIR,"_his",e);try{u.existsSync(o)&&await u.promises.rm(o,{recursive:!0,force:!0}),await u.promises.mkdir(o,{recursive:!0}),c(e,"INFO",`Start extracting backup file for version ${r}`,{projectId:e,codeVersion:r,backupZipPath:t,tempExtractDir:o}),c(e,"DEBUG","Start extracting version backup file",{projectId:e,backupZipPath:t,tempExtractDir:o}),await b(t,o),c(e,"DEBUG",`Version ${r} backup file extraction completed`,{projectId:e,codeVersion:r,tempExtractDir:o}),c(e,"DEBUG","Start traversing version directory",{projectId:e,tempExtractDir:o});const a=await d(o,o,e,l);let w=a;f!=="cpage_config"&&(w=a.filter(D=>D.name!=="cpage_config.json"));const g={files:w};return c(e,"INFO",`Version ${r} project content obtained`,{projectId:e,codeVersion:r,fileCount:g.files?g.files.length:0,command:f,elapsedMs:Date.now()-i}),g}finally{try{u.existsSync(o)&&(await u.promises.rm(o,{recursive:!0,force:!0}),c(e,"INFO",`Temporary directory cleaned: ${o}`,{projectId:e,codeVersion:r}))}catch(a){c(e,"WARN",`Clean temporary directory failed: ${a.message}`,{projectId:e,codeVersion:r,tempExtractDir:o,error:a.message})}}}export{$ as getProjectContent,h as getProjectContentByVersion,d as traverseDirectory,S as isBinaryFile,p as isImageFile};
@@ -1 +1 @@
1
- import s from"fs";import f from"path";import{log as e}from"../log/logUtils.js";async function n(a,r){try{const t=f.join(a,r);return s.existsSync(t)?s.statSync(t).isDirectory()?(s.rmSync(t,{recursive:!0,force:!0}),e("default","INFO",`\u6210\u529F\u5220\u9664\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939: ${t}`),!0):(e("default","WARN",`\u76EE\u6807\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${t}`),!1):(e("default","INFO",`\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939\u4E0D\u5B58\u5728: ${t}`),!0)}catch(t){return e("default","ERROR",`\u5220\u9664\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939\u5931\u8D25: ${t.message}`),e("default","ERROR",`\u76EE\u6807\u8DEF\u5F84: ${f.join(a,r)}`),!1}}async function c(a){try{const{INIT_PROJECT_DIR:r,INIT_PROJECT_NAME:t}=a;if(!r||!t)return e("default","WARN","INIT_PROJECT_DIR \u6216 INIT_PROJECT_NAME \u914D\u7F6E\u7F3A\u5931"),!1;e("default","INFO","\u5F00\u59CB\u6E05\u7406\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939..."),e("default","INFO",`\u76EE\u6807\u76EE\u5F55: ${r}`),e("default","INFO",`\u9879\u76EE\u540D\u79F0: ${t}`);const u=await n(r,t);return u?e("default","INFO","\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939\u6E05\u7406\u5B8C\u6210"):e("default","ERROR","\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939\u6E05\u7406\u5931\u8D25"),u}catch(r){return e("default","ERROR",`\u6E05\u7406\u521D\u59CB\u5316\u9879\u76EE\u6587\u4EF6\u5939\u65F6\u53D1\u751F\u9519\u8BEF: ${r.message}`),!1}}export{n as deleteInitProjectFolder,c as cleanupInitProjectOnStartup};
1
+ import o from"fs";import n from"path";import{log as e}from"../log/logUtils.js";async function c(i,r){try{const t=n.join(i,r);return o.existsSync(t)?o.statSync(t).isDirectory()?(o.rmSync(t,{recursive:!0,force:!0}),e("default","INFO",`Successfully deleted initialization project directory: ${t}`),!0):(e("default","WARN",`Target path is not a directory: ${t}`),!1):(e("default","INFO",`Initialization project directory does not exist: ${t}`),!0)}catch(t){return e("default","ERROR",`Delete initialization project directory failed: ${t.message}`),e("default","ERROR",`Target path: ${n.join(i,r)}`),!1}}async function l(i){try{const{INIT_PROJECT_DIR:r,INIT_PROJECT_NAME:t}=i;if(!r||!t)return e("default","WARN","INIT_PROJECT_DIR or INIT_PROJECT_NAME configuration missing"),!1;e("default","INFO","Start cleaning initialization project directory..."),e("default","INFO",`Target directory: ${r}`),e("default","INFO",`Project name: ${t}`);const a=await c(r,t);return a?e("default","INFO","Initialization project directory cleanup completed"):e("default","ERROR","Initialization project directory cleanup failed"),a}catch(r){return e("default","ERROR",`Clean initialization project directory failed: ${r.message}`),!1}}export{c as deleteInitProjectFolder,l as cleanupInitProjectOnStartup};
@@ -1 +1 @@
1
- import n from"fs";import s from"path";import E from"../../appConfig/index.js";import{log as m}from"../log/logUtils.js";import{ValidationError as h,SystemError as f,FileError as N}from"../error/errorHandler.js";async function u(t,a,c=null){try{if(!t)throw new h("\u9879\u76EEID\u4E0D\u80FD\u4E3A\u7A7A",{field:"projectId"});if(!a)throw new h("\u6587\u4EF6\u4E0D\u80FD\u4E3A\u7A7A",{field:"file"});if(!a.path)throw new h("\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548",{field:"file.path"});m(t,"INFO","\u5F00\u59CB\u4E0A\u4F20\u9644\u4EF6\u6587\u4EF6",{projectId:t,fileName:c,originalName:a.originalname,tempPath:a.path});const r=s.join(E.PROJECT_SOURCE_DIR,t);if(!n.existsSync(r))throw new h("\u9879\u76EE\u4E0D\u5B58\u5728",{field:"projectId"});const e=s.join(r,".attachments");n.existsSync(e)||(await n.promises.mkdir(e,{recursive:!0}),m(t,"INFO","\u521B\u5EFA\u9644\u4EF6\u76EE\u5F55",{attachmentsDir:e}));let i;c?i=c:i=a.originalname;let o=s.join(e,i);if(n.existsSync(o)){const p=Date.now(),g=Math.round(Math.random()*1e6),w=s.extname(i);i=`${s.basename(i,w)}_${p}_${g}${w}`,o=s.join(e,i)}try{await n.promises.rename(a.path,o)}catch(p){if(p.code==="EXDEV")m(t,"INFO","\u8DE8\u8BBE\u5907\u79FB\u52A8\uFF0C\u4F7F\u7528\u590D\u5236\u65B9\u5F0F",{tempPath:a.path,finalPath:o}),await n.promises.copyFile(a.path,o),await n.promises.unlink(a.path);else throw p}const l=s.relative(r,o);return m(t,"INFO","\u9644\u4EF6\u6587\u4EF6\u4E0A\u4F20\u6210\u529F",{projectId:t,originalName:a.originalname,fileName:i,relativePath:l,finalFilePath:o}),{fileName:i,relativePath:l}}catch(r){if(a&&a.path&&n.existsSync(a.path))try{await n.promises.unlink(a.path),m(t,"INFO","\u6E05\u7406\u4E34\u65F6\u6587\u4EF6",{tempPath:a.path})}catch(e){m(t,"WARN","\u6E05\u7406\u4E34\u65F6\u6587\u4EF6\u5931\u8D25",{tempPath:a.path,error:e.message})}throw m(t,"ERROR","\u4E0A\u4F20\u9644\u4EF6\u6587\u4EF6\u5931\u8D25",{projectId:t,originalName:a?.originalname,error:r.message}),r instanceof h||r instanceof f||r instanceof N?r:new f(`\u4E0A\u4F20\u9644\u4EF6\u6587\u4EF6\u5931\u8D25: ${r.message}`,{projectId:t,originalError:r.message})}}export{u as uploadAttachmentFile};
1
+ import n from"fs";import s from"path";import g from"../../appConfig/index.js";import{log as m}from"../log/logUtils.js";import{ValidationError as h,SystemError as w,FileError as u}from"../error/errorHandler.js";async function d(t,a,c=null){try{if(!t)throw new h("Project ID cannot be empty",{field:"projectId"});if(!a)throw new h("File cannot be empty",{field:"file"});if(!a.path)throw new h("File path is invalid",{field:"file.path"});m(t,"INFO","Start uploading attachment file",{projectId:t,fileName:c,originalName:a.originalname,tempPath:a.path});const e=s.join(g.PROJECT_SOURCE_DIR,t);if(!n.existsSync(e))throw new h("Project does not exist",{field:"projectId"});const r=s.join(e,".attachments");n.existsSync(r)||(await n.promises.mkdir(r,{recursive:!0}),m(t,"INFO","Create attachment directory",{attachmentsDir:r}));let i;c?i=c:i=a.originalname;let o=s.join(r,i);if(n.existsSync(o)){const l=Date.now(),y=Math.round(Math.random()*1e6),f=s.extname(i);i=`${s.basename(i,f)}_${l}_${y}${f}`,o=s.join(r,i)}try{await n.promises.rename(a.path,o)}catch(l){if(l.code==="EXDEV")m(t,"INFO","Cross-device move, using copy method",{tempPath:a.path,finalPath:o}),await n.promises.copyFile(a.path,o),await n.promises.unlink(a.path);else throw l}const p=s.relative(e,o);return m(t,"INFO","Attachment file uploaded successfully",{projectId:t,originalName:a.originalname,fileName:i,relativePath:p,finalFilePath:o}),{fileName:i,relativePath:p}}catch(e){if(a&&a.path&&n.existsSync(a.path))try{await n.promises.unlink(a.path),m(t,"INFO","Clean temporary file",{tempPath:a.path})}catch(r){m(t,"WARN","Clean temporary file failed",{tempPath:a.path,error:r.message})}throw m(t,"ERROR","Upload attachment file failed",{projectId:t,originalName:a?.originalname,error:e.message}),e instanceof h||e instanceof w||e instanceof u?e:new w(`Upload attachment file failed: ${e.message}`,{projectId:t,originalError:e.message})}}export{d as uploadAttachmentFile};
@@ -1,3 +1,3 @@
1
- import g from"path";import T from"os";import f from"fs-extra";import{spawn as S}from"cross-spawn";import k from"tree-kill";import{fileURLToPath as E}from"url";const O=g.dirname(E(import.meta.url)),c={name:"nuwax-file-server",pidDir:g.join(T.tmpdir(),"nuwax-file-server"),pidFileName:"server.pid",defaultStopTimeout:3e4,checkInterval:500};function p(){return g.join(c.pidDir,c.pidFileName)}function m(){try{const e=p();if(!f.existsSync(e))return null;const s=f.readFileSync(e,"utf8"),o=JSON.parse(s);return!o||typeof o.pid!="number"?null:o}catch(e){return e.code!=="ENOENT"&&console.error(`\u8BFB\u53D6 PID \u6587\u4EF6\u5931\u8D25: ${e.message}`),null}}function h(e){try{const s=p();f.ensureDirSync(c.pidDir),f.writeFileSync(s,JSON.stringify(e,null,2)),console.debug(`PID \u6587\u4EF6\u5DF2\u5199\u5165: ${s}`)}catch(s){throw console.error(`\u5199\u5165 PID \u6587\u4EF6\u5931\u8D25: ${s.message}`),s}}function $(){try{const e=p();f.existsSync(e)&&(f.removeSync(e),console.debug(`PID \u6587\u4EF6\u5DF2\u5220\u9664: ${e}`))}catch(e){console.error(`\u5220\u9664 PID \u6587\u4EF6\u5931\u8D25: ${e.message}`)}}function u(e){try{return process.kill(e,0),!0}catch(s){return s.code!=="ESRCH"}}function I(){return process.platform==="win32"}async function w(e,s=!1){return new Promise(o=>{if(!u(e)){console.debug(`\u8FDB\u7A0B ${e} \u4E0D\u5B58\u5728\uFF0C\u89C6\u4E3A\u5DF2\u505C\u6B62`),o(!0);return}const n=s?"SIGKILL":"SIGTERM",i=I()?"taskkill":"tree-kill";if(console.debug(`\u4F7F\u7528 ${i} \u505C\u6B62\u8FDB\u7A0B ${e} (\u4FE1\u53F7: ${n})`),I()){const r=s?["/F","/PID",String(e)]:["/PID",String(e)],a=S("taskkill",r,{stdio:["ignore","pipe","pipe"],windowsHide:!0});let d="";a.stdout.on("data",t=>{d+=t.toString()}),a.stderr.on("data",t=>{d+=t.toString()}),a.on("error",t=>{console.error(`\u505C\u6B62\u8FDB\u7A0B\u5931\u8D25: ${t.message}`),o(!1)}),a.on("close",t=>{t===0?(console.debug(`\u8FDB\u7A0B ${e} \u5DF2\u505C\u6B62`),o(!0)):(console.warn(`taskkill \u9000\u51FA\u7801: ${t}, \u8F93\u51FA: ${d}`),s?o(!1):w(e,!0).then(o))})}else k(e,n,r=>{r?r.code==="ESRCH"?(console.debug(`\u8FDB\u7A0B ${e} \u4E0D\u5B58\u5728`),o(!0)):(console.error(`\u505C\u6B62\u8FDB\u7A0B\u5931\u8D25: ${r.message}`),o(!1)):(console.debug(`\u8FDB\u7A0B ${e} \u5DF2\u505C\u6B62`),o(!0))})})}async function D(e,s=c.defaultStopTimeout){const o=Date.now();for(;u(e);){if(Date.now()-o>s)return console.warn(`\u7B49\u5F85\u8FDB\u7A0B ${e} \u505C\u6B62\u8D85\u65F6 (${s}ms)`),!1;await new Promise(i=>setTimeout(i,c.checkInterval))}const n=Date.now()-o;return console.debug(`\u8FDB\u7A0B ${e} \u5DF2\u5728 ${n}ms \u540E\u505C\u6B62`),!0}async function v(e={}){const{env:s,port:o,config:n}=e;console.log(`\u542F\u52A8\u670D\u52A1 ${c.name}...`);const i=m();if(i&&u(i.pid))return{success:!1,pid:i.pid,message:`\u670D\u52A1\u5DF2\u5728\u8FD0\u884C\u4E2D (PID: ${i.pid})`};const r={...process.env};s&&(r.NODE_ENV=s,console.log(`\u73AF\u5883: ${s}`)),o&&(r.PORT=o,console.log(`\u7AEF\u53E3: ${o}`)),n&&(r.CONFIG_FILE=n,console.log(`\u914D\u7F6E\u6587\u4EF6: ${n}`));const a=g.join(O,"..","server.js"),t=S("node",[a,...[]],{env:r,stdio:["pipe","pipe","pipe"],detached:!0,cwd:process.cwd()});if(t.stdout.on("data",l=>{process.stdout.write(l)}),t.stderr.on("data",l=>{process.stderr.write(l)}),t.on("error",l=>{console.error(`\u542F\u52A8\u670D\u52A1\u5931\u8D25: ${l.message}`)}),await new Promise(l=>setTimeout(l,2e3)),!u(t.pid))return{success:!1,pid:null,message:"\u670D\u52A1\u542F\u52A8\u5931\u8D25"};const P={pid:t.pid,startedAt:new Date().toISOString(),env:s||process.env.NODE_ENV||"production",port:o||process.env.PORT||"60000",version:require("../../package.json").version,platform:process.platform};return h(P),t.unref(),console.log(`\u670D\u52A1\u5DF2\u542F\u52A8 (PID: ${t.pid})`),console.log(`\u8FD0\u884C\u5730\u5740: http://localhost:${P.port}`),{success:!0,pid:t.pid,message:"\u670D\u52A1\u542F\u52A8\u6210\u529F"}}async function y(e={}){const{force:s=!1,timeout:o=c.defaultStopTimeout}=e;console.log(`\u505C\u6B62\u670D\u52A1 ${c.name}...`);const n=m();if(!n)return{success:!1,message:"\u672A\u627E\u5230\u8FD0\u884C\u4E2D\u7684\u670D\u52A1"};if(!u(n.pid))return console.log("\u670D\u52A1\u8FDB\u7A0B\u5DF2\u505C\u6B62\uFF0C\u6E05\u7406 PID \u6587\u4EF6..."),$(),{success:!0,message:"\u670D\u52A1\u5DF2\u505C\u6B62\uFF08\u8FDB\u7A0B\u5DF2\u9000\u51FA\uFF09"};if(!await w(n.pid,s))return{success:!1,message:"\u505C\u6B62\u670D\u52A1\u5931\u8D25"};const r=await D(n.pid,o);return $(),r?{success:!0,message:"\u670D\u52A1\u5DF2\u505C\u6B62"}:{success:!1,message:"\u670D\u52A1\u505C\u6B62\u8D85\u65F6"}}async function R(e={}){console.log(`\u91CD\u542F\u670D\u52A1 ${c.name}...`);const s=await y(e);!s.success&&s.message!=="\u672A\u627E\u5230\u8FD0\u884C\u4E2D\u7684\u670D\u52A1"&&console.warn(`\u505C\u6B62\u670D\u52A1\u5931\u8D25: ${s.message}`),await new Promise(n=>setTimeout(n,2e3));const o=await v(e);return o.success?{success:!0,pid:o.pid,message:"\u670D\u52A1\u5DF2\u91CD\u542F"}:{success:!1,pid:null,message:`\u91CD\u542F\u5931\u8D25: ${o.message}`}}function N(){const e=m();return e?u(e.pid)?{running:!0,pidInfo:e,message:"\u670D\u52A1\u8FD0\u884C\u4E2D"}:{running:!1,pidInfo:e,message:"\u670D\u52A1\u8FDB\u7A0B\u4E0D\u5B58\u5728"}:{running:!1,pidInfo:null,message:"\u670D\u52A1\u672A\u8FD0\u884C"}}function F(e){try{const s=new Date(e),o=new Date;if(isNaN(s.getTime()))return"\u672A\u77E5";const n=Math.floor((o-s)/1e3),i=Math.floor(n/3600),r=Math.floor(n%3600/60),a=n%60;return i>0?`${i}\u5C0F\u65F6 ${r}\u5206 ${a}\u79D2`:r>0?`${r}\u5206 ${a}\u79D2`:`${a}\u79D2`}catch{return"\u672A\u77E5"}}export{c as SERVICE_CONFIG,p as getPidFilePath,m as readPidFile,h as writePidFile,$ as deletePidFile,u as isProcessRunning,w as stopProcess,D as waitForProcessStop,v as startService,y as stopService,R as restartService,N as getServiceStatus,I as isWindows,F as formatUptime};if(process.argv[1]&&import.meta.url.endsWith(process.argv[1].replace(/\\/g,"/").replace(/^.*[\/\\]/,""))){const e=N();console.log(`
2
- ${c.name} \u670D\u52A1\u72B6\u6001:
3
- `),console.log(` \u8FD0\u884C\u72B6\u6001: ${e.running?"\u8FD0\u884C\u4E2D":"\u5DF2\u505C\u6B62"}`),e.pidInfo&&(console.log(` \u8FDB\u7A0B ID: ${e.pidInfo.pid}`),console.log(` \u73AF\u5883: ${e.pidInfo.env||"\u672A\u77E5"}`),console.log(` \u7AEF\u53E3: ${e.pidInfo.port||"\u672A\u77E5"}`),console.log(` \u7248\u672C: ${e.pidInfo.version||"\u672A\u77E5"}`),console.log(` \u5E73\u53F0: ${e.pidInfo.platform||"\u672A\u77E5"}`),console.log(` \u542F\u52A8\u65F6\u95F4: ${e.pidInfo.startedAt||"\u672A\u77E5"}`),console.log(` \u8FD0\u884C\u65F6\u95F4: ${F(e.pidInfo.startedAt)}`)),console.log(` PID \u6587\u4EF6: ${p()}`),console.log(""),process.exit(e.running?0:1)}
1
+ import g from"path";import E from"os";import p from"fs-extra";import{spawn as P}from"cross-spawn";import N from"tree-kill";import{fileURLToPath as x}from"url";const F=g.dirname(x(import.meta.url)),c={name:"nuwax-file-server",pidDir:g.join(E.tmpdir(),"nuwax-file-server"),pidFileName:"server.pid",defaultStopTimeout:3e4,checkInterval:500};function d(){return g.join(c.pidDir,c.pidFileName)}function m(){try{const e=d();if(!p.existsSync(e))return null;const s=p.readFileSync(e,"utf8"),o=JSON.parse(s);return!o||typeof o.pid!="number"?null:o}catch(e){return e.code!=="ENOENT"&&console.error(`Read PID file failed: ${e.message}`),null}}function I(e){try{const s=d();p.ensureDirSync(c.pidDir),p.writeFileSync(s,JSON.stringify(e,null,2)),console.debug(`PID file written: ${s}`)}catch(s){throw console.error(`Write PID file failed: ${s.message}`),s}}function S(){try{const e=d();p.existsSync(e)&&(p.removeSync(e),console.debug(`PID file deleted: ${e}`))}catch(e){console.error(`Delete PID file failed: ${e.message}`)}}function u(e){try{return process.kill(e,0),!0}catch(s){return s.code!=="ESRCH"}}function $(){return process.platform==="win32"}async function w(e,s=!1){return new Promise(o=>{if(!u(e)){console.debug(`Process ${e} does not exist, already stopped`),o(!0);return}const t=s?"SIGKILL":"SIGTERM",i=$()?"taskkill":"tree-kill";if(console.debug(`Use ${i} to stop process ${e} (signal: ${t})`),$()){const r=s?["/F","/PID",String(e)]:["/PID",String(e)],a=P("taskkill",r,{stdio:["ignore","pipe","pipe"],windowsHide:!0});let f="";a.stdout.on("data",n=>{f+=n.toString()}),a.stderr.on("data",n=>{f+=n.toString()}),a.on("error",n=>{console.error(`Stop process failed: ${n.message}`),o(!1)}),a.on("close",n=>{n===0?(console.debug(`Process ${e} stopped`),o(!0)):(console.warn(`taskkill exit code: ${n}, output: ${f}`),s?o(!1):w(e,!0).then(o))})}else N(e,t,r=>{r?r.code==="ESRCH"?(console.debug(`Process ${e} does not exist`),o(!0)):(console.error(`Stop process failed: ${r.message}`),o(!1)):(console.debug(`Process ${e} stopped`),o(!0))})})}async function h(e,s=c.defaultStopTimeout){const o=Date.now();for(;u(e);){if(Date.now()-o>s)return console.warn(`Wait for process ${e} to stop timeout (${s}ms)`),!1;await new Promise(i=>setTimeout(i,c.checkInterval))}const t=Date.now()-o;return console.debug(`Process ${e} stopped after ${t}ms`),!0}async function D(e={}){const{env:s,port:o,config:t}=e;console.log(`Start service ${c.name}...`);const i=m();if(i&&u(i.pid))return{success:!1,pid:i.pid,message:`Service is already running (PID: ${i.pid})`};const r={...process.env};s&&(r.NODE_ENV=s,console.log(`Environment: ${s}`)),o&&(r.PORT=o,console.log(`Port: ${o}`)),t&&(r.CONFIG_FILE=t,console.log(`Configuration file: ${t}`));const a=g.join(F,"..","server.js"),n=P("node",[a,...[]],{env:r,stdio:["pipe","pipe","pipe"],detached:!0,cwd:process.cwd()});if(n.stdout.on("data",l=>{process.stdout.write(l)}),n.stderr.on("data",l=>{process.stderr.write(l)}),n.on("error",l=>{console.error(`Start service failed: ${l.message}`)}),await new Promise(l=>setTimeout(l,2e3)),!u(n.pid))return{success:!1,pid:null,message:"Service start failed"};const v={pid:n.pid,startedAt:new Date().toISOString(),env:s||process.env.NODE_ENV||"production",port:o||process.env.PORT||"60000",version:require("../../package.json").version,platform:process.platform};return I(v),n.unref(),console.log(`Service started (PID: ${n.pid})`),console.log(`Service address: http://localhost:${v.port}`),{success:!0,pid:n.pid,message:"Service started successfully"}}async function y(e={}){const{force:s=!1,timeout:o=c.defaultStopTimeout}=e;console.log(`Stop service ${c.name}...`);const t=m();if(!t)return{success:!1,message:"Service not found"};if(!u(t.pid))return console.log("Service process has stopped, clean PID file..."),S(),{success:!0,message:"Service has stopped (process has exited)"};if(!await w(t.pid,s))return{success:!1,message:"Stop service failed"};const r=await h(t.pid,o);return S(),r?{success:!0,message:"Service has stopped"}:{success:!1,message:"Service stop timeout"}}async function T(e={}){console.log(`Restart service ${c.name}...`);const s=await y(e);!s.success&&s.message!=="Service not found"&&console.warn(`Stop service failed: ${s.message}`),await new Promise(t=>setTimeout(t,2e3));const o=await D(e);return o.success?{success:!0,pid:o.pid,message:"Service has restarted"}:{success:!1,pid:null,message:`Restart failed: ${o.message}`}}function k(){const e=m();return e?u(e.pid)?{running:!0,pidInfo:e,message:"Service running"}:{running:!1,pidInfo:e,message:"Service process does not exist"}:{running:!1,pidInfo:null,message:"Service not running"}}function R(e){try{const s=new Date(e),o=new Date;if(isNaN(s.getTime()))return"unknown";const t=Math.floor((o-s)/1e3),i=Math.floor(t/3600),r=Math.floor(t%3600/60),a=t%60;return i>0?`${i} hours ${r} minutes ${a} seconds`:r>0?`${r} minutes ${a} seconds`:`${a} seconds`}catch{return"unknown"}}export{c as SERVICE_CONFIG,d as getPidFilePath,m as readPidFile,I as writePidFile,S as deletePidFile,u as isProcessRunning,w as stopProcess,h as waitForProcessStop,D as startService,y as stopService,T as restartService,k as getServiceStatus,$ as isWindows,R as formatUptime};if(process.argv[1]&&import.meta.url.endsWith(process.argv[1].replace(/\\/g,"/").replace(/^.*[\/\\]/,""))){const e=k();console.log(`
2
+ ${c.name} Service status:
3
+ `),console.log(` Running status: ${e.running?"Running":"Stopped"}`),e.pidInfo&&(console.log(` Process ID: ${e.pidInfo.pid}`),console.log(` Environment: ${e.pidInfo.env||"Unknown"}`),console.log(` Port: ${e.pidInfo.port||"Unknown"}`),console.log(` Version: ${e.pidInfo.version||"Unknown"}`),console.log(` Platform: ${e.pidInfo.platform||"Unknown"}`),console.log(` Started at: ${e.pidInfo.startedAt||"Unknown"}`),console.log(` Uptime: ${R(e.pidInfo.startedAt)}`)),console.log(` PID file: ${d()}`),console.log(""),process.exit(e.running?0:1)}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "nuwax-file-server",
3
3
  "displayName": "nuwax-file-server",
4
- "version": "1.2.4",
5
- "description": "跨平台的文件服务部署工具,支持 start/stop/restart 命令行操作",
4
+ "version": "1.2.6",
5
+ "description": "Cross-platform file service deployment tool with start/stop/restart CLI commands",
6
6
  "type": "module",
7
7
  "main": "index.js",
8
8
  "bin": {