nuwax-file-server 1.2.3 → 1.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +131 -151
- package/dist/appConfig/index.js +1 -1
- package/dist/cli.js +1 -1
- package/dist/config/swagger.js +1 -1
- package/dist/routes/buildRoutes.js +1 -1
- package/dist/routes/codeRoutes.js +1 -1
- package/dist/routes/computerRoutes.js +1 -1
- package/dist/routes/projectRoutes.js +1 -1
- package/dist/scheduler/pnpmPruneScheduler.js +2 -2
- package/dist/server.js +1 -1
- package/dist/service/codeService.js +2 -2
- package/dist/service/projectService.js +1 -1
- package/dist/utils/build/buildProjectUtils.js +4 -4
- package/dist/utils/build/keepAliveDevUtils.js +1 -1
- package/dist/utils/build/processManager.js +9 -9
- package/dist/utils/build/restartDevUtils.js +1 -1
- package/dist/utils/build/startDevUtils.js +1 -1
- package/dist/utils/build/stopDevUtils.js +2 -2
- package/dist/utils/build/syntaxCheckUtils.js +7 -7
- package/dist/utils/buildArg/extraArgsUtils.js +1 -1
- package/dist/utils/buildArg/portPool.js +1 -1
- package/dist/utils/buildArg/portUtils.js +7 -7
- package/dist/utils/buildDependency/dependencyManager.js +17 -17
- package/dist/utils/buildJudge/aliveJudgeUtils.js +1 -1
- package/dist/utils/buildJudge/restartJudgeUtils.js +1 -1
- package/dist/utils/buildPermission/permissionManager.js +3 -3
- package/dist/utils/common/npmrcUtils.js +3 -3
- package/dist/utils/common/zipUtils.js +1 -1
- package/dist/utils/computer/computerFileUtils.js +1 -1
- package/dist/utils/computer/computerUtils.js +1 -1
- package/dist/utils/envUtils.js +3 -3
- package/dist/utils/error/buildErrorParser.js +18 -18
- package/dist/utils/error/errorHandler.js +1 -1
- package/dist/utils/log/getDevLogUtils.js +2 -2
- package/dist/utils/log/logCacheManager.js +2 -2
- package/dist/utils/log/logUtils.js +2 -2
- package/dist/utils/project/backupUtils.js +1 -1
- package/dist/utils/project/copyProjectUtils.js +1 -1
- package/dist/utils/project/frameworkDetectorUtils.js +1 -1
- package/dist/utils/project/getContentUtils.js +1 -1
- package/dist/utils/project/initProjectCleanupUtils.js +1 -1
- package/dist/utils/project/uploadAttachmentFileUtils.js +1 -1
- package/dist/utils/serviceManager.js +3 -3
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log as e}from"../log/logUtils.js";class
|
|
1
|
+
import{log as e}from"../log/logUtils.js";class r{constructor(){this.portRangeStart=4e3,this.portRangeEnd=55e3,this.reservedRangeStart=8e3,this.reservedRangeEnd=9e3,this.availablePorts=new Set,this.allocatedPorts=new Map,this._initializePortPool()}_initializePortPool(){for(let a=this.portRangeStart;a<=this.portRangeEnd;a++)a>=this.reservedRangeStart&&a<=this.reservedRangeEnd||this.availablePorts.add(a);const t=this.reservedRangeEnd-this.reservedRangeStart+1;e("SYSTEM","INFO","Port pool initialized",{portRange:`${this.portRangeStart}-${this.portRangeEnd}`,totalPorts:this.availablePorts.size,reservedCount:t})}allocate(t){if(this.allocatedPorts.has(t)){const o=this.allocatedPorts.get(t);return e(t,"INFO","Project already has allocated port, reuse",{port:o}),o}if(this.availablePorts.size===0)throw new Error(`Port pool exhausted: no available ports in range ${this.portRangeStart}-${this.portRangeEnd}`);const a=this.availablePorts.values().next().value;return this.availablePorts.delete(a),this.allocatedPorts.set(t,a),e(t,"INFO","Port pool allocated port",{port:a,totalAllocated:this.allocatedPorts.size,remainingAvailable:this.availablePorts.size}),a}release(t){const a=this.allocatedPorts.get(t);a&&(this.allocatedPorts.delete(t),this.availablePorts.add(a),e(t,"INFO","Port pool released port",{port:a,totalAllocated:this.allocatedPorts.size,remainingAvailable:this.availablePorts.size}))}getPort(t){return this.allocatedPorts.get(t)||null}getStatus(){return{portRange:`${this.portRangeStart}-${this.portRangeEnd}`,totalAllocated:this.allocatedPorts.size,allocations:Array.from(this.allocatedPorts.entries()).map(([t,a])=>({projectId:t,port:a}))}}clear(){for(const t of this.allocatedPorts.values())this.availablePorts.add(t);this.allocatedPorts.clear(),e("SYSTEM","INFO","Port pool cleared and reset",{availablePorts:this.availablePorts.size,allocatedPorts:this.allocatedPorts.size})}}const s=new r;export default s;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import p from"fs";import G from"net";import{execSync as d}from"child_process";import{log as a}from"../log/logUtils.js";function E(t){if(!t||typeof t!="string")return;let n=t.match(/--port\s+(\d{2,5})/);if(n||(n=t.match(/-p\s+(\d{2,5})/),n)||(n=t.match(/PORT\s*=\s*(\d{2,5})/),n))return Number(n[1])}function k(t){return new Promise(n=>{const r=Number(t)||3e3,e=2e3;function s(o,c){if(c>e){n(r);return}if(P(o)){s(o+1,c+1);return}const i=G.createServer();i.unref();let m=!1;i.on("error",()=>{m||(m=!0,s(o+1,c+1))}),i.listen(o,()=>{if(m){try{i.close()}catch{}return}m=!0;const l=i.address().port;i.close(()=>n(l))})}s(r,0)})}function P(t){return!!($(t)||U(t))}function $(t){try{const n=`ss -ltn 2>/dev/null | grep ":${Number(t)} "`,r=d(n,{stdio:["ignore","pipe","ignore"],shell:"/bin/sh",timeout:2e3,killSignal:"SIGKILL"}),e=String(r||"");return e.trim().length>0&&e.includes("LISTEN")}catch{return!1}}function U(t){try{let n;if(process.platform==="linux")n=`netstat -ltn 2>/dev/null | grep ":${Number(t)} "`;else if(process.platform==="darwin")n=`netstat -an 2>/dev/null | grep "LISTEN" | grep "\\.${Number(t)} "`;else return!1;const r=d(n,{stdio:["ignore","pipe","ignore"],shell:"/bin/sh",timeout:2e3,killSignal:"SIGKILL"});return String(r||"").trim().length>0}catch{return!1}}function z(t){try{const n=`lsof -Pi :${Number(t)} -sTCP:LISTEN -n`,r=d(n,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"});return String(r||"").trim().length>0}catch{return!1}}function w(t){try{try{const n=`pgrep -P ${t}`,r=d(n,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"}),s=String(r||"").trim().split(`
|
|
2
2
|
`).filter(o=>o).map(o=>Number(o));if(s.length>0)return s}catch{}try{const n=`ps -eo pid,ppid | awk '$2==${t} {print $1}'`,r=d(n,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"});return String(r||"").trim().split(`
|
|
3
|
-
`).filter(o=>o).map(o=>Number(o))}catch{}if(process.platform==="linux")try{const n=`/proc/${t}/task/${t}/children`;if(
|
|
4
|
-
`),i=[];for(const l of c){if(!l)continue;const f=l.match(/(?:0\.0\.0\.0|\[::\]|127\.0\.0\.1|\*):(\d+)/);if(f){const u=Number(f[1]);u&&!i.includes(u)&&i.push(u)}}const m=Date.now()-r;return a(n,"DEBUG","ss
|
|
5
|
-
`),i=[];for(const l of c){if(!l)continue;const f=l.match(/(?:0\.0\.0\.0|:::|\*:|127\.0\.0\.1:)(\d+)/);if(f){const u=Number(f[1]);u&&!i.includes(u)&&i.push(u)}}const m=Date.now()-r;return a(n,"DEBUG","netstat
|
|
6
|
-
`);if(c.length<=1){const l=Date.now()-r;return a(n,"DEBUG","lsof
|
|
7
|
-
`).filter(o=>o).map(o=>Number(o))}catch{return[]}}function
|
|
8
|
-
`).reverse();for(const f of l){if(f.match(/^\[[\d\/\s:]+\]/)||/(EADDRINUSE|address already in use|Error:\s*listen)/i.test(f)||/^(\s|\t)*(code|errno|syscall|address|port)\s*:/i.test(f))continue;const u=f.match(/https?:\/\/[^\s:]+:(\d{2,5})/);if(u)return Number(u[1]);const g=f.match(/(?:listening|running|started)[^\n]*\bport\b\s*:?\s*(\d{2,5})/i);if(g)return Number(g[1]);const h=f.match(/(?:listening|running|started)\s+on\s*:(\d{2,5})/i);if(h)return Number(h[1]);const
|
|
3
|
+
`).filter(o=>o).map(o=>Number(o))}catch{}if(process.platform==="linux")try{const n=`/proc/${t}/task/${t}/children`;if(p.existsSync(n))return p.readFileSync(n,"utf8").trim().split(" ").filter(s=>s).map(s=>Number(s))}catch{}return[]}catch{return[]}}function x(t,n="default"){try{const r=`ps -p ${t} -o pid=`;try{d(r,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"})}catch{return[]}const e=b(t,new Set,n);return Array.from(e.keys()).sort((s,o)=>s-o)}catch{return[]}}function b(t,n=new Set,r="default"){const e=new Map;if(n.has(t))return e;n.add(t);try{const s=B(t,r);if(s.forEach(c=>{e.set(c,t)}),s.length>0)return e;const o=w(t);for(const c of o)b(c,n,r).forEach((m,l)=>{e.set(l,m)});return e}catch{return e}}function D(t,n="default"){try{a(n,"DEBUG","Check if process exists",{pid:t});const r=`ps -p ${t} -o pid=`;try{d(r,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"}),a(n,"DEBUG","Process exists, start recursive query ports",{pid:t})}catch{return a(n,"DEBUG","Process does not exist",{pid:t}),new Map}return b(t,new Set,n)}catch(r){const e=r&&r.message?r.message:String(r);return a(n,"ERROR","getPortsAndPidsByPid exception",{pid:t,error:e}),new Map}}function B(t,n="default"){const r=Date.now(),e=T(t,n);if(e.length>0){const o=Date.now()-r;return a(n,"INFO","Using ss to query ports",{pid:t,ports:e,duration:`${o}ms`,method:"ss"}),e}const s=v(t,n);if(s.length>0){const o=Date.now()-r;return a(n,"INFO","Using netstat to query ports",{pid:t,ports:s,duration:`${o}ms`,method:"netstat"}),s}return[]}function T(t,n="default"){const r=Date.now();try{a(n,"DEBUG","Try using ss command to query ports",{pid:t});const e=`ss -ltnp 2>/dev/null | grep "pid=${t},"`,s=d(e,{stdio:["ignore","pipe","ignore"],shell:"/bin/sh",timeout:3e3,killSignal:"SIGKILL"}),c=String(s||"").trim().split(`
|
|
4
|
+
`),i=[];for(const l of c){if(!l)continue;const f=l.match(/(?:0\.0\.0\.0|\[::\]|127\.0\.0\.1|\*):(\d+)/);if(f){const u=Number(f[1]);u&&!i.includes(u)&&i.push(u)}}const m=Date.now()-r;return a(n,"DEBUG","ss command executed successfully",{pid:t,portsCount:i.length,duration:`${m}ms`}),i}catch(e){const s=Date.now()-r,o=e&&e.message?e.message:String(e);return a(n,"DEBUG","ss command execution failed",{pid:t,error:o,duration:`${s}ms`}),[]}}function v(t,n="default"){const r=Date.now();try{let e;if(process.platform==="linux")a(n,"DEBUG","Try using netstat command to query ports",{pid:t}),e=`netstat -ltnp 2>/dev/null | grep "${t}/"`;else return process.platform==="darwin"?(a(n,"DEBUG","macOS system skip netstat",{pid:t}),[]):(a(n,"DEBUG",`${process.platform} system does not support netstat`,{pid:t}),[]);const s=d(e,{stdio:["ignore","pipe","ignore"],shell:"/bin/sh",timeout:3e3,killSignal:"SIGKILL"}),c=String(s||"").trim().split(`
|
|
5
|
+
`),i=[];for(const l of c){if(!l)continue;const f=l.match(/(?:0\.0\.0\.0|:::|\*:|127\.0\.0\.1:)(\d+)/);if(f){const u=Number(f[1]);u&&!i.includes(u)&&i.push(u)}}const m=Date.now()-r;return a(n,"DEBUG","netstat command executed successfully",{pid:t,portsCount:i.length,duration:`${m}ms`}),i}catch(e){const s=Date.now()-r,o=e&&e.message?e.message:String(e);return a(n,"DEBUG","netstat command execution failed",{pid:t,error:o,duration:`${s}ms`}),[]}}function _(t,n="default"){const r=Date.now();try{a(n,"DEBUG","Try using lsof command to query ports",{pid:t});const e=`lsof -Pan -p ${t} -iTCP -sTCP:LISTEN -n`,s=d(e,{stdio:["ignore","pipe","ignore"],timeout:3e3,killSignal:"SIGKILL"}),c=String(s||"").trim().split(`
|
|
6
|
+
`);if(c.length<=1){const l=Date.now()-r;return a(n,"DEBUG","lsof command did not find listening ports",{pid:t,duration:`${l}ms`}),[]}const i=[];for(let l=1;l<c.length;l++){const f=c[l].trim();if(!f)continue;const u=f.match(/(\*|localhost|127\.0\.0\.1|0\.0\.0\.0):(\d+)\s*\(LISTEN\)/);if(u){const g=Number(u[2]);g&&!i.includes(g)&&i.push(g)}}const m=Date.now()-r;return a(n,"DEBUG","lsof command executed successfully",{pid:t,portsCount:i.length,duration:`${m}ms`}),i}catch(e){const s=Date.now()-r,o=e&&e.message?e.message:String(e);return a(n,"DEBUG","lsof command execution failed",{pid:t,error:o,duration:`${s}ms`}),[]}}function M(t){try{const n=`lsof -ti:${t}`,r=d(n,{stdio:["ignore","pipe","ignore"],timeout:2e3,killSignal:"SIGKILL"});return String(r||"").trim().split(`
|
|
7
|
+
`).filter(o=>o).map(o=>Number(o))}catch{return[]}}function I(t,n=1e4,r=500,e="default"){return new Promise(s=>{let o=!1,c=0;const i=Math.ceil(n/r);a(e,"INFO","Start waiting for listening port",{pid:t,timeoutMs:n,intervalMs:r,maxAttempts:i});function m(){if(!o){c++,a(e,"INFO",`Query listening port (\u7B2C${c}/${i}\u6B21)`,{pid:t,attempts:c});try{a(e,"DEBUG","Start calling getPortsAndPidsByPid",{pid:t});const u=Date.now(),g=D(t,e),h=Date.now()-u;if(a(e,"DEBUG","getPortsAndPidsByPid called successfully",{pid:t,mapSize:g.size,duration:`${h}ms`}),g.size>0){o=!0;const y=Array.from(g.keys()).sort((N,L)=>N-L)[0],S=g.get(y);a(e,"INFO","Successfully detected listening port",{pid:t,actualPid:S,port:y,attempts:c,allPorts:Array.from(g.keys())}),s({port:y,pid:Number(S)});return}a(e,"DEBUG","No listening port found in this query",{pid:t,attempts:c})}catch(u){const g=u&&u.message?u.message:String(u);a(e,"ERROR","Exception occurred when querying ports",{pid:t,attempts:c,error:g,stack:u&&u.stack?u.stack:""})}}}if(m(),o)return;const l=setInterval(()=>{o||(m(),o&&(clearInterval(l),clearTimeout(f)))},r),f=setTimeout(()=>{o||(o=!0,clearInterval(l),a(e,"WARN","Waiting for listening port timeout",{pid:t,timeoutMs:n,attempts:c}),s(void 0))},n)})}function A(t,n=1e4,r=300){return new Promise(e=>{const s=Date.now();function o(){if(P(t)){e(!0);return}if(Date.now()-s>=n){e(!1);return}setTimeout(o,r)}o()})}function F(t,n=15e3){return new Promise(r=>{let e=!1;function s(m){const l=m.split(`
|
|
8
|
+
`).reverse();for(const f of l){if(f.match(/^\[[\d\/\s:]+\]/)||/(EADDRINUSE|address already in use|Error:\s*listen)/i.test(f)||/^(\s|\t)*(code|errno|syscall|address|port)\s*:/i.test(f))continue;const u=f.match(/https?:\/\/[^\s:]+:(\d{2,5})/);if(u)return Number(u[1]);const g=f.match(/(?:listening|running|started)[^\n]*\bport\b\s*:?\s*(\d{2,5})/i);if(g)return Number(g[1]);const h=f.match(/(?:listening|running|started)\s+on\s*:(\d{2,5})/i);if(h)return Number(h[1]);const y=f.match(/(?:Local|Network|local|network):\s*https?:\/\/[^\s:]+:(\d{2,5})/i);if(y)return Number(y[1]);const S=f.match(/ready\s*-\s*started\s*server[^:]*:(\d{2,5})/i);if(S)return Number(S[1])}}function o(){if(!e)try{if(!p.existsSync(t))return;const m=p.statSync(t),l=Math.min(64*1024,m.size),f=p.openSync(t,"r"),u=Buffer.alloc(l);p.readSync(f,u,0,l,m.size-l),p.closeSync(f);const g=u.toString("utf8"),h=s(g);h&&(e=!0,r(h))}catch{}}if(o(),e)return;const c=setInterval(()=>{e||(o(),e&&(clearInterval(c),clearTimeout(i)))},500),i=setTimeout(()=>{e||(e=!0,clearInterval(c),r(void 0))},n)})}function C(t,n){const r=[],e=String(n);if(!t||typeof t!="string")return r;const s=t.toLowerCase();return s.includes("vite")?(n&&r.push("--port",e,"--strictPort"),r):s.includes("webpack")||s.includes("vitepress")||s.includes("umi")||s.includes("serve")?(r.push("--port",e),r):s.includes("next")||s.includes("nuxt")?(r.push("-p",e),r):(r.push("--port",e),r)}export{E as parsePortFromScript,k as getAvailablePort,F as waitPortFromLog,C as buildPortArgsForScript,P as isPortListening,A as waitPortListening,x as getPortsByPid,I as waitPortFromPid,M as getPidsByPort,w as getChildPids,D as getPortsAndPidsByPid};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import{exec as
|
|
2
|
-
|
|
3
|
-
`;e(
|
|
4
|
-
`;e(
|
|
5
|
-
|
|
6
|
-
${
|
|
7
|
-
`;return e(
|
|
8
|
-
${
|
|
9
|
-
`;e(
|
|
10
|
-
`;if(e(
|
|
11
|
-
${
|
|
12
|
-
|
|
13
|
-
`+
|
|
14
|
-
`;e(
|
|
15
|
-
`;e(
|
|
16
|
-
`;e(
|
|
17
|
-
${
|
|
1
|
+
import{exec as N,spawn as T}from"child_process";import p from"path";import k from"fs";import{log as m}from"../log/logUtils.js";function x(o){try{return k.statSync(o).mtimeMs}catch{return 0}}function v(o){const u=p.join(o,"package.json"),l=p.join(o,"package-lock.json"),r=p.join(o,"yarn.lock"),s=p.join(o,"node_modules");if(!k.existsSync(s))return!0;const e=x(u),g=Math.max(x(l),x(r)),M=x(s);return Math.max(e,g)>M}async function I(o,u=null){const l=p.join(o,"node_modules"),r=u||p.basename(o);if(k.existsSync(l)){m(r,"INFO","Found node_modules folder, deleting",{projectPath:o,nodeModulesPath:l});try{await k.promises.rm(l,{recursive:!0,force:!0}),m(r,"INFO","node_modules folder deleted successfully",{projectPath:o,nodeModulesPath:l})}catch(n){m(r,"WARN",`Failed to delete node_modules folder: ${n.message}`,{projectPath:o,nodeModulesPath:l,error:n.message})}}const s=["package-lock.json","yarn.lock","pnpm-lock.yaml"];for(const n of s){const e=p.join(o,n);if(k.existsSync(e)){m(r,"INFO",`Found ${n} file, deleting`,{projectPath:o,lockFilePath:e});try{await k.promises.unlink(e),m(r,"INFO",`${n} file deleted successfully`,{projectPath:o,lockFilePath:e})}catch(g){m(r,"WARN",`Failed to delete ${n} file: ${g.message}`,{projectPath:o,lockFilePath:e,error:g.message})}}}}function O(o,u,l,r={}){const{outStream:s,tempOutStream:n,safeWrite:e}=r;return s&&n&&e?new Promise((g,M)=>{const F=`cd ${l} && pnpm install --prefer-offline`,d=Date.now(),y=`Start installing dependencies
|
|
2
|
+
Command: pnpm install --prefer-offline
|
|
3
|
+
`;e(s,y,"Main log"),e(n,y,"Temp log");let f=0;const D=setInterval(()=>{f++;const t=`Installing dependencies... (Elapsed time: ${Math.floor((Date.now()-d)/1e3)} seconds)
|
|
4
|
+
`;e(s,t,"Main log"),e(n,t,"Temp log")},5e3),$=T("sh",["-c",F],{cwd:l,env:process.env,stdio:["ignore","pipe","pipe"]});let S="",c="";$.stdout&&$.stdout.on("data",i=>{const t=i.toString();S+=t,e(s,t,"Main log"),e(n,t,"Temp log")}),$.stderr&&$.stderr.on("data",i=>{const t=i.toString();c+=t,e(s,t,"Main log"),e(n,t,"Temp log")}),$.on("exit",(i,t)=>{clearInterval(D);const w=((Date.now()-d)/1e3).toFixed(2);if(i!==0){const a=`Dependency installation failed (Elapsed time: ${w} seconds)
|
|
5
|
+
Exit code: ${i}, Signal: ${t}
|
|
6
|
+
${c||"No error information"}
|
|
7
|
+
`;return e(s,a,"Main log"),e(n,a,"Temp log"),M(new Error(`Dependency installation failed: Exit code ${i}, Signal ${t}
|
|
8
|
+
${c}`))}if(c&&c.includes("Error")&&!c.includes("warning")){const a=`Warning occurred during dependency installation: ${c}
|
|
9
|
+
`;e(s,a,"Main log"),e(n,a,"Temp log")}const E=`\u2713 Dependency installation successful (Elapsed time: ${w} seconds)
|
|
10
|
+
`;if(e(s,E,"Main log"),e(n,E,"Temp log"),S||c){const a=`Installation details:
|
|
11
|
+
${S||"(No standard output)"}${c?`
|
|
12
|
+
Warning information:
|
|
13
|
+
`+c:""}
|
|
14
|
+
`;e(s,a,"Main log"),e(n,a,"Temp log")}else{const a=`(Silent mode: No detailed output, dependency successfully linked from store to node_modules)
|
|
15
|
+
`;e(s,a,"Main log"),e(n,a,"Temp log")}g(S)}),$.on("error",i=>{clearInterval(D);const w=`Dependency installation process error (Elapsed time: ${((Date.now()-d)/1e3).toFixed(2)} seconds): ${i.message}
|
|
16
|
+
`;e(s,w,"Main log"),e(n,w,"Temp log"),M(new Error(`Dependency installation failed: ${i.message}`))})}):new Promise((g,M)=>{const F=`cd ${l} && pnpm install --prefer-offline --reporter=silent --loglevel=error`;m(u,"INFO","Start executing dependency installation command",{command:F,projectPath:l}),N(F,{maxBuffer:10*1024*1024,env:process.env},(d,y,f)=>{if(d)return m(u,"ERROR","Dependency installation failed",{error:d.message,code:d.code,stderr:f||d.message,stdout:y||""}),M(new Error(`Dependency installation failed: ${d.message}
|
|
17
|
+
${f||d.message}`));f&&f.includes("Error")&&!f.includes("warning")&&m(u,"WARN","Warning or error occurred during dependency installation",{stderr:f}),m(u,"INFO","Dependency installation completed",{stdout:y.substring(0,500)}),g(y)})})}export{x as getFileMtime,v as shouldInstallDeps,O as installDependencies,I as removeNodeModules};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import d from"http";import T from"https";import{URL as N}from"url";import{log as
|
|
1
|
+
import d from"http";import T from"https";import{URL as N}from"url";import{log as m}from"../log/logUtils.js";async function A(n,f,a,p={}){const c=Number(p.timeoutMs)||1500,u=Number(f);if(!Number.isFinite(u)||u<=0)return!1;const h=a?"/"+String(a).replace(/^\/+/,""):"/",o=`http://127.0.0.1:${u}${h}`;return new Promise(s=>{let t=!1;const r=new N(o),i=(r.protocol==="https:"?T:d).request({method:"GET",hostname:r.hostname,port:r.port,path:r.pathname+r.search,headers:{"User-Agent":"xagi-keepalive-check"}},e=>{if(t)return;t=!0;const l=e.statusCode>=200&&e.statusCode<300;m(n,"INFO","Alive detection HTTP response",{statusCode:e.statusCode,url:o,alive:l}),e.resume(),s(l)});i.on("error",e=>{t||(t=!0,m(n,"WARN","Alive detection HTTP request error",{error:e&&e.message,url:o}),s(!1))}),i.setTimeout(c,()=>{t||(t=!0,m(n,"INFO","Alive detection HTTP request timeout",{url:o,timeoutMs:c}),i.destroy(),s(!1))});try{i.end()}catch{t||(t=!0,s(!1))}})}export{A as isProjectAlive};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log as
|
|
1
|
+
import{log as r}from"../log/logUtils.js";function e(t){if(!t||typeof t!="string")return!1;const s=[/package\.json$/i,/vite\.config\.(js|ts|mjs|cjs)$/i,/webpack\.config\.(js|ts|mjs|cjs)$/i,/rollup\.config\.(js|ts|mjs|cjs)$/i,/next\.config\.(js|ts|mjs|cjs)$/i,/nuxt\.config\.(js|ts|mjs|cjs)$/i,/tailwind\.config\.(js|ts|mjs|cjs)$/i,/postcss\.config\.(js|ts|mjs|cjs)$/i,/babel\.config\.(js|ts|mjs|cjs)$/i,/tsconfig\.json$/i,/\.env$/i,/\.env\..*$/i,/yarn\.lock$/i,/package-lock\.json$/i,/pnpm-lock\.yaml$/i];for(const n of s)if(n.test(t))return r(null,"INFO",`Detected file that needs to be restarted: ${t}`,{fileName:t,pattern:n.toString()}),!0;return!1}function i(t){if(!Array.isArray(t)||t.length===0)return!1;for(const s of t)if(!(!s||typeof s.name!="string")&&e(s.name))return!0;return!1}export{e as shouldRestartForSingleFile,i as shouldRestartDevServer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{exec as f}from"child_process";import
|
|
2
|
-
`)){const u=
|
|
1
|
+
import{exec as f}from"child_process";import s from"path";import e from"fs";import{log as w}from"../log/logUtils.js";async function d(m){try{const t=await e.promises.readdir(m,{withFileTypes:!0});for(const i of t){const a=s.join(m,i.name);if(i.isDirectory())await d(a);else if(i.isFile()&&(i.name.includes("bin")||i.name.endsWith(".exe")||!i.name.includes(".")||i.name.match(/^(esbuild|vite|webpack|rollup)$/)))try{await e.promises.chmod(a,493),await new Promise(o=>{f(`xattr -d com.apple.quarantine "${a}"`,()=>o())})}catch{}}}catch{}}async function y(m){try{const t=s.join(m,"node_modules");if(!e.existsSync(t))return;const i=s.join(t,".bin");if(e.existsSync(i)){const l=await e.promises.readdir(i,{withFileTypes:!0});for(const o of l){if(!o.isFile())continue;const n=s.join(i,o.name);try{await e.promises.chmod(n,493)}catch{}try{const c=(await e.promises.readFile(n,"utf8")).trim();if(c&&!c.startsWith("#!/")&&!c.includes(`
|
|
2
|
+
`)){const u=s.resolve(s.dirname(n),c);if(e.existsSync(u)){try{await e.promises.chmod(u,493)}catch{}try{const p=s.relative(s.dirname(n),u);await e.promises.unlink(n).catch(()=>{}),await e.promises.symlink(p,n)}catch{const h=`#!/usr/bin/env bash
|
|
3
3
|
DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
4
4
|
exec "$DIR/${c}" "$@"
|
|
5
|
-
`;try{await e.promises.writeFile(
|
|
5
|
+
`;try{await e.promises.writeFile(n,h,"utf8"),await e.promises.chmod(n,493)}catch{}}}}}catch{}try{await new Promise(r=>{f(`xattr -d com.apple.quarantine "${n}"`,()=>r())})}catch{}}}const a=["@esbuild","esbuild","vite","webpack","rollup"];for(const l of a){const o=s.join(t,l);e.existsSync(o)&&await d(o)}}catch(t){w(null,"WARN","Problem occurred when fixing executable permissions (ignore and continue)",{error:t&&t.message})}}export{d as fixExecutablePermissionsRecursive,y as ensureDevBinariesExecutable};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
# \u81EA\u52A8\u751F\u6210\u4E8E ${
|
|
1
|
+
import c from"fs";import i from"path";import{log as a,getCSTDateTimeString as l}from"../log/logUtils.js";async function o(r,m=null){const t=m||i.basename(r),e=i.join(r,".npmrc"),n=`# pnpm \u78C1\u76D8\u7A7A\u95F4\u4F18\u5316\u914D\u7F6E
|
|
2
|
+
# \u81EA\u52A8\u751F\u6210\u4E8E ${l()}
|
|
3
3
|
|
|
4
4
|
package-import-method=hardlink
|
|
5
5
|
auto-install-peers=true
|
|
6
6
|
registry=https://registry.npmmirror.com
|
|
7
|
-
`;try{return
|
|
7
|
+
`;try{return c.existsSync(e)?(a(t,"INFO",".npmrc file already exists, skip creation",{projectPath:r,npmrcPath:e}),{success:!0,created:!1,message:".npmrc file already exists",npmrcPath:e}):(await c.promises.writeFile(e,n,"utf8"),a(t,"INFO",".npmrc file created successfully",{projectPath:r,npmrcPath:e}),{success:!0,created:!0,message:".npmrc file created successfully",npmrcPath:e})}catch(s){return a(t,"WARN",`.npmrc file creation failed: ${s.message}`,{projectPath:r,npmrcPath:e,error:s.message}),{success:!1,created:!1,message:`.npmrc file creation failed: ${s.message}`,error:s.message}}}export{o as createPnpmNpmrc};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"fs";import E from"path";import h from"yauzl";import{FileError as g}from"../error/errorHandler.js";function k(c,i){return new Promise((d,r)=>{h.open(c,{lazyEntries:!0},(m,e)=>{if(m)return r(new g(`\u65E0\u6CD5\u6253\u5F00\u538B\u7F29\u5305: ${m.message}`,{zipPath:c,originalError:m.message}));e.readEntry(),e.on("entry",n=>{if(/\/$/.test(n.fileName)){const t=E.join(i,n.fileName);try{l.mkdirSync(t,{recursive:!0})}catch(s){console.warn("[extractZip] mkdir for directory entry failed, skip this dir",{dirPath:t,code:s.code,message:s.message}),e.readEntry();return}e.readEntry()}else e.openReadStream(n,(t,s)=>{if(t)return r(new g(`Failed to read zip entry: ${t.message}`,{entry:n.fileName,originalError:t.message}));const a=E.join(i,n.fileName),u=E.dirname(a);try{l.mkdirSync(u,{recursive:!0})}catch(o){console.warn("[extractZip] mkdir for file entry failed, skip this file",{dirPath:u,filePath:a,code:o.code,message:o.message}),e.readEntry();return}try{if(l.existsSync(a)&&l.statSync(a).isDirectory()){e.readEntry();return}}catch(o){return r(new g(`Failed to check file status: ${o.message}`,{filePath:a,originalError:o.message}))}const f=l.createWriteStream(a);s.pipe(f),f.on("close",()=>{e.readEntry()}),f.on("error",o=>{r(new g(`Failed to write file: ${o.message}`,{filePath:a,originalError:o.message}))})})}),e.on("end",()=>{d()}),e.on("error",n=>{r(new g(`Error occurred during unzip: ${n.message}`,{zipPath:c,originalError:n.message}))})})})}const y=new Map,w=50;function S(c){return new Promise(i=>{try{const d=l.statSync(c),r=`${c}:${d.mtimeMs}:${d.size}`;if(y.has(r))return i(y.get(r));h.open(c,{lazyEntries:!0},(m,e)=>{if(m)return i(null);const n=new Map;e.readEntry(),e.on("entry",t=>{const s=t.fileName.replace(/\\/g,"/");/\/$/.test(t.fileName)||n.set(s,t),e.readEntry()}),e.on("end",()=>{e.close(),y.size>=w&&Array.from(y.keys()).slice(0,Math.floor(w/2)).forEach(s=>y.delete(s)),y.set(r,n),i(n)}),e.on("error",()=>{e.close(),i(null)})})}catch{i(null)}})}function $(c,i,d){return new Promise(async r=>{try{const m=await S(c);if(!m)return r(!1);const e=i.replace(/^[\/\\]+/,"").replace(/\\/g,"/");if(!m.has(e))return r(!1);h.open(c,{lazyEntries:!1},(n,t)=>{if(n)return r(!1);let s=null;for(const a of t.entries)if(a.fileName.replace(/\\/g,"/")===e&&!/\/$/.test(a.fileName)){s=a;break}if(!s)return t.close(),r(!1);t.openReadStream(s,(a,u)=>{if(a||!u)return t.close(),r(!1);const f=E.dirname(d);try{l.mkdirSync(f,{recursive:!0})}catch{return t.close(),r(!1)}const o=l.createWriteStream(d);u.pipe(o),o.on("close",()=>{t.close(),r(!0)}),o.on("error",()=>{t.close(),r(!1)})})})}catch{r(!1)}})}export{k as extractZip,$ as extractSingleFileFromZip};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import m from"fs";import w from"path";import N from"archiver";import P from"../../appConfig/index.js";import{log as s}from"../log/logUtils.js";import{ValidationError as g,SystemError as F}from"../error/errorHandler.js";function v(l){try{const a=m.readFileSync(l);if(a.includes(0))return!0;const i=a.toString("utf-8");for(let c=0;c<i.length;c++){const r=i.charCodeAt(c);if(r<32&&r!==9&&r!==10&&r!==13)return!0}return!1}catch(a){return s("system","WARN",`\u68C0\u6D4B\u4E8C\u8FDB\u5236\u6587\u4EF6\u5931\u8D25: ${l}`,{error:a.message}),!1}}function j(l){const a=w.extname(l).toLowerCase();return[".jpg",".jpeg",".png",".gif",".bmp",".webp",".svg",".ico",".avif"].includes(a)}async function C(l,a,i,c){const r=[],R=await m.promises.readdir(l,{withFileTypes:!0});R.sort((n,o)=>n.isDirectory()&&!o.isDirectory()?-1:!n.isDirectory()&&o.isDirectory()?1:n.name.toLowerCase().localeCompare(o.name.toLowerCase()));for(const n of R){const o=w.join(l,n.name);if(!(n.name.startsWith(".")||(P.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).includes(n.name))&&!(n.isDirectory()&&P.TRAVERSE_EXCLUDE_DIRS.includes(n.name)))if(n.isDirectory()){const e=await C(o,a,i,c);if(e.length===0){const d=a||l,h=w.relative(d,o).replace(/\\/g,"/");r.push({name:h,isDir:!0})}else r.push(...e)}else try{const e=await m.promises.stat(o),d=a||l,h=w.relative(d,o).replace(/\\/g,"/"),t=v(o),f=n.isSymbolicLink();let p=null;if(c){const y=h.split("/").map(I=>encodeURIComponent(I)).join("/");p=`${c}/${y}`}const E={name:h,isDir:!1,binary:t,fileProxyUrl:p,isLink:f};r.push(E)}catch(e){s(i,"WARN",`\u5904\u7406\u6587\u4EF6\u5931\u8D25: ${o}`,{error:e.message})}}return r}async function A(l,a,i){const c=Date.now(),r=`computer:${l}:${a}`,R=P.COMPUTER_WORKSPACE_DIR;if(!l)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!a)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});const n=String(l),o=String(a),u=w.join(R,n,o);if(!m.existsSync(u))return s(r,"INFO","\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8FD4\u56DE\u7A7A\u5217\u8868",{targetDir:u,userId:n,cId:o}),{files:[]};s(r,"DEBUG","\u5F00\u59CB\u83B7\u53D6\u7528\u6237\u6587\u4EF6\u5217\u8868",{targetDir:u,userId:n,cId:o});try{const e=await C(u,u,r,i);return s(r,"INFO","\u7528\u6237\u6587\u4EF6\u5217\u8868\u83B7\u53D6\u5B8C\u6210",{fileCount:e.length,targetDir:u,userId:n,cId:o,elapsedMs:Date.now()-c}),{files:e}}catch(e){throw s(r,"ERROR","\u83B7\u53D6\u7528\u6237\u6587\u4EF6\u5217\u8868\u5931\u8D25",{targetDir:u,userId:n,cId:o,error:e.message,elapsedMs:Date.now()-c}),new F(`\u83B7\u53D6\u6587\u4EF6\u5217\u8868\u5931\u8D25: ${e.message}`,{targetDir:u,originalError:e.message})}}async function k(l,a,i){const c=Date.now(),r=`computer:${l}:${a}`,R=P.COMPUTER_WORKSPACE_DIR;if(!l)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!a)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});if(!Array.isArray(i))throw new g("files\u5FC5\u987B\u662F\u6570\u7EC4",{field:"files"});const n=String(l),o=String(a),u=w.join(R,n,o);m.existsSync(u)||m.mkdirSync(u,{recursive:!0});for(let e=0;e<i.length;e++){const d=i[e];if(!d||typeof d.operation!="string")throw new g(`files[${e}].operation \u4E0D\u80FD\u4E3A\u7A7A`,{field:`files[${e}].operation`});if(!d.name||typeof d.name!="string")throw new g(`files[${e}].name \u4E0D\u80FD\u4E3A\u7A7A`,{field:`files[${e}].name`});const h=d.operation.toLowerCase();if(!["create","delete","rename","modify"].includes(h))throw new g(`files[${e}].operation \u5FC5\u987B\u662F create\u3001delete\u3001rename \u6216 modify \u4E4B\u4E00`,{field:`files[${e}].operation`});if(h==="rename"&&!d.renameFrom)throw new g(`files[${e}].renameFrom \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u91CD\u547D\u540D\u64CD\u4F5C\u9700\u8981\uFF09`,{field:`files[${e}].renameFrom`});if(h==="modify"&&d.isDir!==!0&&typeof d.contents!="string")throw new g(`files[${e}].contents \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\uFF08\u4FEE\u6539\u64CD\u4F5C\u9700\u8981\uFF09`,{field:`files[${e}].contents`})}s(r,"DEBUG","\u5F00\u59CB\u66F4\u65B0\u7528\u6237\u6587\u4EF6",{userId:n,cId:o,filesCount:i.length});try{for(const e of i){const d=e.operation.toLowerCase(),h=e.name,t=w.normalize(h).replace(/^[\/\\]+/,""),f=w.join(u,t),p=w.resolve(f),E=w.resolve(u);if(!p.startsWith(E+w.sep)&&p!==E){s(r,"WARN","\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5B89\u5168\uFF0C\u8DF3\u8FC7",{filePath:t,resolvedPath:p});continue}switch(d){case"create":{if(e.isDir===!0){if(m.existsSync(f)){if((await m.promises.stat(f)).isFile())throw new g("\u65E0\u6CD5\u521B\u5EFA\u76EE\u5F55\uFF0C\u5DF2\u5B58\u5728\u540C\u540D\u6587\u4EF6",{filePath:t});s(r,"INFO","\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u521B\u5EFA",{filePath:t});break}await m.promises.mkdir(f,{recursive:!0}),s(r,"INFO","\u76EE\u5F55\u521B\u5EFA\u6210\u529F",{filePath:t});break}if(m.existsSync(f)){if((await m.promises.stat(f)).isDirectory())throw new g("\u65E0\u6CD5\u521B\u5EFA\u6587\u4EF6\uFF0C\u5DF2\u5B58\u5728\u540C\u540D\u76EE\u5F55",{filePath:t});s(r,"INFO","\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7\u521B\u5EFA",{filePath:t});break}await m.promises.mkdir(w.dirname(f),{recursive:!0});const y=e.contents||"";await m.promises.writeFile(f,y,"utf8"),s(r,"INFO","\u6587\u4EF6\u521B\u5EFA\u6210\u529F",{filePath:t});break}case"delete":{m.existsSync(f)?(await m.promises.stat(f)).isDirectory()?(await m.promises.rm(f,{recursive:!0,force:!0}),s(r,"INFO","\u76EE\u5F55\u5220\u9664\u6210\u529F",{filePath:t})):(await m.promises.unlink(f),s(r,"INFO","\u6587\u4EF6\u5220\u9664\u6210\u529F",{filePath:t})):s(r,"WARN","\u8981\u5220\u9664\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u4E0D\u5B58\u5728",{filePath:t});break}case"rename":{const y=e.renameFrom;if(!y||typeof y!="string"){s(r,"WARN","\u91CD\u547D\u540D\u64CD\u4F5C\u7F3A\u5C11 renameFrom",{filePath:t});break}const I=w.normalize(y).replace(/^[\/\\]+/,""),D=w.join(u,I),S=w.resolve(D);if(!S.startsWith(E+w.sep)&&S!==E){s(r,"WARN","\u6E90\u8DEF\u5F84\u4E0D\u5B89\u5168\uFF0C\u8DF3\u8FC7\u91CD\u547D\u540D",{sourcePath:I,targetPath:t});break}if(m.existsSync(D)){const $=(await m.promises.stat(D)).isDirectory();await m.promises.mkdir(w.dirname(f),{recursive:!0}),await m.promises.rename(D,f),s(r,"INFO",$?"\u76EE\u5F55\u91CD\u547D\u540D\u6210\u529F":"\u6587\u4EF6\u91CD\u547D\u540D\u6210\u529F",{sourcePath:I,targetPath:t})}else s(r,"WARN","\u8981\u91CD\u547D\u540D\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u4E0D\u5B58\u5728",{sourcePath:I});break}case"modify":{if(!m.existsSync(f)){s(r,"WARN","\u8981\u4FEE\u6539\u7684\u6587\u4EF6\u4E0D\u5B58\u5728",{filePath:t});break}if((await m.promises.stat(f)).isDirectory()){s(r,"INFO","\u76EE\u6807\u662F\u76EE\u5F55\uFF0C\u8DF3\u8FC7\u4FEE\u6539",{filePath:t});break}const I=typeof e.contents=="string"?e.contents:"";if(await m.promises.readFile(f,"utf8")===I){s(r,"INFO","\u6587\u4EF6\u5185\u5BB9\u65E0\u53D8\u5316\uFF0C\u8DF3\u8FC7\u5199\u5165",{filePath:t});break}await m.promises.writeFile(f,I,"utf8"),s(r,"INFO","\u6587\u4EF6\u4FEE\u6539\u6210\u529F",{filePath:t});break}default:{s(r,"WARN","\u4E0D\u652F\u6301\u7684\u64CD\u4F5C\u7C7B\u578B",{operation:d,filePath:t});break}}}return s(r,"INFO","\u7528\u6237\u6587\u4EF6\u66F4\u65B0\u6210\u529F",{userId:n,cId:o,filesCount:i.length,elapsedMs:Date.now()-c}),{success:!0,message:"\u7528\u6237\u6587\u4EF6\u66F4\u65B0\u6210\u529F",userId:n,cId:o,filesCount:i.length}}catch(e){throw s(r,"ERROR","\u7528\u6237\u6587\u4EF6\u66F4\u65B0\u5931\u8D25",{userId:n,cId:o,error:e.message,elapsedMs:Date.now()-c}),new F(`\u7528\u6237\u6587\u4EF6\u66F4\u65B0\u5931\u8D25: ${e.message}`,{userId:n,cId:o,originalError:e.message})}}async function O(l,a,i,c){const r=Date.now(),R=`computer:${l}:${a}`,n=P.COMPUTER_WORKSPACE_DIR;if(!l)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!a)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});if(!i)throw new g("\u6587\u4EF6\u4E0D\u80FD\u4E3A\u7A7A",{field:"file"});if(!c||typeof c!="string")throw new g("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A",{field:"filePath"});const o=String(l),u=String(a),e=w.join(n,o,u);m.existsSync(e)||m.mkdirSync(e,{recursive:!0});const d=w.normalize(c).replace(/^[\/\\]+/,""),h=w.join(e,d),t=w.resolve(h),f=w.resolve(e);if(!t.startsWith(f+w.sep)&&t!==f)throw new g("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5B89\u5168\uFF0C\u4E0D\u80FD\u8D85\u51FA\u7528\u6237\u76EE\u5F55",{field:"filePath",providedPath:c,resolvedPath:t});try{if(await m.promises.mkdir(w.dirname(h),{recursive:!0}),i.buffer)await m.promises.writeFile(h,i.buffer);else if(typeof i.contents=="string")await m.promises.writeFile(h,i.contents,"utf8");else throw new g("\u6587\u4EF6\u5185\u5BB9\u683C\u5F0F\u4E0D\u6B63\u786E",{field:"file",hasBuffer:!!i.buffer,hasContents:typeof i.contents});return s(R,"INFO","\u6587\u4EF6\u4E0A\u4F20\u6210\u529F",{userId:o,cId:u,filePath:d,targetPath:t,fileSize:i.buffer?i.buffer.length:i.contents?i.contents.length:0,elapsedMs:Date.now()-r}),{success:!0,message:"\u6587\u4EF6\u4E0A\u4F20\u6210\u529F",fileSize:i.buffer?i.buffer.length:i.contents?i.contents.length:0}}catch(p){throw s(R,"ERROR","\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25",{userId:o,cId:u,filePath:d,error:p.message,elapsedMs:Date.now()-r}),new F(`\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25: ${p.message}`,{userId:o,cId:u,filePath:d,originalError:p.message})}}async function b(l,a,i,c){const r=Date.now(),R=`computer:${l}:${a}`;if(!l)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!a)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});if(!Array.isArray(i))throw new g("files \u5FC5\u987B\u662F\u6570\u7EC4",{field:"files"});if(!Array.isArray(c))throw new g("filePaths \u5FC5\u987B\u662F\u6570\u7EC4",{field:"filePaths"});if(i.length!==c.length)throw new g(`\u6587\u4EF6\u6570\u91CF (${i.length}) \u4E0E\u8DEF\u5F84\u6570\u91CF (${c.length}) \u4E0D\u5339\u914D`,{field:"filePaths"});s(R,"DEBUG","\u5F00\u59CB\u6279\u91CF\u4E0A\u4F20\u6587\u4EF6",{userId:l,cId:a,filesCount:i.length});const n=[];try{for(let e=0;e<i.length;e++){const d=i[e],h=c[e];if(!d){s(R,"WARN","\u6279\u91CF\u4E0A\u4F20\u4E2D\u9047\u5230\u7A7A\u6587\u4EF6\u5BF9\u8C61\uFF0C\u8DF3\u8FC7",{index:e,filePath:h}),n.push({success:!1,filePath:h,error:"\u6587\u4EF6\u5BF9\u8C61\u4E3A\u7A7A"});continue}if(!h||typeof h!="string"){s(R,"WARN","\u6279\u91CF\u4E0A\u4F20\u4E2D\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548\uFF0C\u8DF3\u8FC7",{index:e,originalname:d.originalname}),n.push({success:!1,filePath:h||"",originalname:d.originalname,error:"\u6587\u4EF6\u8DEF\u5F84\u65E0\u6548"});continue}try{const t=await O(l,a,d,h);n.push({success:!0,filePath:h,originalname:d.originalname,...t})}catch(t){s(R,"ERROR","\u6279\u91CF\u4E0A\u4F20\u4E2D\u5355\u4E2A\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25",{filePath:h,originalname:d.originalname,error:t.message}),n.push({success:!1,filePath:h,originalname:d.originalname,error:t.message})}}const o=n.filter(e=>e.success).length,u=n.filter(e=>!e.success).length;return s(R,"INFO","\u6279\u91CF\u4E0A\u4F20\u6587\u4EF6\u5B8C\u6210",{userId:l,cId:a,totalCount:i.length,successCount:o,failCount:u,elapsedMs:Date.now()-r}),{success:!0,message:"\u6279\u91CF\u4E0A\u4F20\u5B8C\u6210",totalCount:i.length,successCount:o,failCount:u,results:n}}catch(o){throw s(R,"ERROR","\u6279\u91CF\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25",{userId:l,cId:a,error:o.message,elapsedMs:Date.now()-r}),new F(`\u6279\u91CF\u4E0A\u4F20\u6587\u4EF6\u5931\u8D25: ${o.message}`,{userId:l,cId:a,originalError:o.message})}}async function T(l,a){const i=Date.now(),c=`computer:${l}:${a}`,r=P.COMPUTER_WORKSPACE_DIR;if(!l)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!a)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});if(!r)throw new F("COMPUTER_WORKSPACE_DIR \u672A\u914D\u7F6E\uFF0C\u65E0\u6CD5\u521B\u5EFA\u538B\u7F29\u5305");const R=String(l),n=String(a),o=w.join(r,R,n);if(!m.existsSync(o)){const t=`${R}_${n}.zip`;s(c,"WARN","\u5DE5\u4F5C\u76EE\u5F55\u4E0D\u5B58\u5728\uFF0C\u8FD4\u56DE\u7A7A\u538B\u7F29\u5305",{targetDir:o,userId:R,cId:n,zipFileName:t});const f=N("zip",{zlib:{level:9}});return f.append(null,{name:`${R}_${n}/`,type:"directory"}),f.on("warning",p=>{if(p.code==="ENOENT")s(c,"WARN","\u521B\u5EFA\u7A7A\u538B\u7F29\u5305\u65F6\u9047\u5230\u6587\u4EF6\u95EE\u9898",{message:p.message,code:p.code});else throw s(c,"ERROR","\u521B\u5EFA\u7A7A\u538B\u7F29\u5305\u65F6\u53D1\u751F\u8B66\u544A",{message:p.message,code:p.code}),p}),f.on("error",p=>{s(c,"ERROR","\u521B\u5EFA\u7A7A\u538B\u7F29\u5305\u5931\u8D25",{message:p.message})}),{archive:f,zipFileName:t}}const u=`${R}_${n}.zip`;s(c,"DEBUG","\u5F00\u59CB\u521B\u5EFA\u5DE5\u4F5C\u76EE\u5F55\u538B\u7F29\u5305",{targetDir:o,zipFileName:u});const e=N("zip",{zlib:{level:9}}),d=P.CONTENT_TRAVERSE_EXCLUDE_FILES||[],h=P.TRAVERSE_EXCLUDE_DIRS||[];return e.directory(o,`${R}_${n}`,t=>{const f=t.name||"",p=f.split(/[\/\\]/).filter(Boolean);if(p.some(y=>y.startsWith(".")))return!1;const E=p[p.length-1];if(d.includes(E)||p.some(y=>h.includes(y)))return!1;try{const y=w.join(o,f),I=m.lstatSync(y);if(I.isSymbolicLink()||I.nlink>1)return!1}catch(y){return s(c,"WARN","\u68C0\u6D4B\u94FE\u63A5\u6587\u4EF6\u65F6\u51FA\u9519\uFF0C\u8DF3\u8FC7\u8BE5\u6587\u4EF6",{filePath:f,error:y.message}),!1}return t}),e.on("warning",t=>{if(t.code==="ENOENT")s(c,"WARN","\u521B\u5EFA\u538B\u7F29\u5305\u65F6\u9047\u5230\u6587\u4EF6\u95EE\u9898",{message:t.message,code:t.code});else throw s(c,"ERROR","\u521B\u5EFA\u538B\u7F29\u5305\u65F6\u53D1\u751F\u8B66\u544A",{message:t.message,code:t.code}),t}),e.on("error",t=>{s(c,"ERROR","\u521B\u5EFA\u538B\u7F29\u5305\u5931\u8D25",{message:t.message,elapsedMs:Date.now()-i})}),e.on("end",()=>{s(c,"INFO","\u5DE5\u4F5C\u76EE\u5F55\u538B\u7F29\u5305\u521B\u5EFA\u5B8C\u6210",{targetDir:o,zipFileName:u,elapsedMs:Date.now()-i})}),{archive:e,zipFileName:u}}export{A as getFileList,k as updateFiles,O as uploadFile,b as uploadFiles,T as downloadAllFiles};
|
|
1
|
+
import f from"fs";import h from"path";import S from"archiver";import I from"../../appConfig/index.js";import{log as i}from"../log/logUtils.js";import{ValidationError as g,SystemError as P}from"../error/errorHandler.js";async function k(d,m,s,l){const n=[],w=await f.promises.readdir(d,{withFileTypes:!0});w.sort((r,o)=>r.isDirectory()&&!o.isDirectory()?-1:!r.isDirectory()&&o.isDirectory()?1:r.name.toLowerCase().localeCompare(o.name.toLowerCase()));for(const r of w){const o=h.join(d,r.name);if(!(r.name.startsWith(".")||(I.CONTENT_TRAVERSE_EXCLUDE_FILES||[]).includes(r.name))&&!(r.isDirectory()&&I.TRAVERSE_EXCLUDE_DIRS.includes(r.name)))if(r.isDirectory()){const e=await k(o,m,s,l);if(e.length===0){const c=m||d,p=h.relative(c,o).replace(/\\/g,"/");n.push({name:p,isDir:!0})}else n.push(...e)}else try{const e=m||d,c=h.relative(e,o).replace(/\\/g,"/"),p=r.isSymbolicLink();let t=null;if(l){const y=c.split("/").map(F=>encodeURIComponent(F)).join("/");t=`${l}/${y}`}const a={name:c,isDir:!1,fileProxyUrl:t,isLink:p};n.push(a)}catch(e){i(s,"WARN",`\u5904\u7406\u6587\u4EF6\u5931\u8D25: ${o}`,{error:e.message})}}return n}async function O(d,m,s){const l=Date.now(),n=`computer:${d}:${m}`,w=I.COMPUTER_WORKSPACE_DIR;if(!d)throw new g("userId \u4E0D\u80FD\u4E3A\u7A7A",{field:"userId"});if(!m)throw new g("cId \u4E0D\u80FD\u4E3A\u7A7A",{field:"cId"});const r=String(d),o=String(m),u=h.join(w,r,o);if(!f.existsSync(u))return i(n,"INFO","Directory does not exist, returning empty list",{targetDir:u,userId:r,cId:o}),{files:[]};i(n,"DEBUG","Start getting user file list",{targetDir:u,userId:r,cId:o});try{const e=await k(u,u,n,s);return i(n,"INFO","User file list obtained successfully",{fileCount:e.length,targetDir:u,userId:r,cId:o,elapsedMs:Date.now()-l}),{files:e}}catch(e){throw i(n,"ERROR","Failed to get user file list",{targetDir:u,userId:r,cId:o,error:e.message,elapsedMs:Date.now()-l}),new P(`Failed to get file list: ${e.message}`,{targetDir:u,originalError:e.message})}}async function $(d,m,s){const l=Date.now(),n=`computer:${d}:${m}`,w=I.COMPUTER_WORKSPACE_DIR;if(!d)throw new g("userId cannot be empty",{field:"userId"});if(!m)throw new g("cId cannot be empty",{field:"cId"});if(!Array.isArray(s))throw new g("files must be an array",{field:"files"});const r=String(d),o=String(m),u=h.join(w,r,o);f.existsSync(u)||f.mkdirSync(u,{recursive:!0});for(let e=0;e<s.length;e++){const c=s[e];if(!c||typeof c.operation!="string")throw new g(`files[${e}].operation cannot be empty`,{field:`files[${e}].operation`});if(!c.name||typeof c.name!="string")throw new g(`files[${e}].name cannot be empty`,{field:`files[${e}].name`});const p=c.operation.toLowerCase();if(!["create","delete","rename","modify"].includes(p))throw new g(`files[${e}].operation must be one of create, delete, rename or modify`,{field:`files[${e}].operation`});if(p==="rename"&&!c.renameFrom)throw new g(`files[${e}].renameFrom cannot be empty (rename operation requires)`,{field:`files[${e}].renameFrom`});if(p==="modify"&&c.isDir!==!0&&typeof c.contents!="string")throw new g(`files[${e}].contents must be a string (modify operation requires)`,{field:`files[${e}].contents`})}i(n,"DEBUG","Start updating user files",{userId:r,cId:o,filesCount:s.length});try{for(const e of s){const c=e.operation.toLowerCase(),p=e.name,t=h.normalize(p).replace(/^[\/\\]+/,""),a=h.join(u,t),y=h.resolve(a),F=h.resolve(u);if(!y.startsWith(F+h.sep)&&y!==F){i(n,"WARN","File path is not secure, skipping",{filePath:t,resolvedPath:y});continue}switch(c){case"create":{if(e.isDir===!0){if(f.existsSync(a)){if((await f.promises.stat(a)).isFile())throw new g("Cannot create directory, file with the same name already exists",{filePath:t});i(n,"INFO","Directory already exists, skipping creation",{filePath:t});break}await f.promises.mkdir(a,{recursive:!0}),i(n,"INFO","Directory created successfully",{filePath:t});break}if(f.existsSync(a)){if((await f.promises.stat(a)).isDirectory())throw new g("Cannot create file, directory with the same name already exists",{filePath:t});i(n,"INFO","File already exists, skipping creation",{filePath:t});break}await f.promises.mkdir(h.dirname(a),{recursive:!0});const R=e.contents||"";await f.promises.writeFile(a,R,"utf8"),i(n,"INFO","File created successfully",{filePath:t});break}case"delete":{f.existsSync(a)?(await f.promises.stat(a)).isDirectory()?(await f.promises.rm(a,{recursive:!0,force:!0}),i(n,"INFO","Directory deleted successfully",{filePath:t})):(await f.promises.unlink(a),i(n,"INFO","File deleted successfully",{filePath:t})):i(n,"WARN","The file or directory to be deleted does not exist",{filePath:t});break}case"rename":{const R=e.renameFrom;if(!R||typeof R!="string"){i(n,"WARN","Rename operation missing renameFrom",{filePath:t});break}const E=h.normalize(R).replace(/^[\/\\]+/,""),D=h.join(u,E),b=h.resolve(D);if(!b.startsWith(F+h.sep)&&b!==F){i(n,"WARN","Source path is not secure, skipping rename",{sourcePath:E,targetPath:t});break}if(f.existsSync(D)){const C=(await f.promises.stat(D)).isDirectory();await f.promises.mkdir(h.dirname(a),{recursive:!0}),await f.promises.rename(D,a),i(n,"INFO",C?"Directory renamed successfully":"File renamed successfully",{sourcePath:E,targetPath:t})}else i(n,"WARN","The file or directory to be renamed does not exist",{sourcePath:E});break}case"modify":{if(!f.existsSync(a)){i(n,"WARN","The file to be modified does not exist",{filePath:t});break}if((await f.promises.stat(a)).isDirectory()){i(n,"INFO","The target is a directory, skipping modification",{filePath:t});break}const E=typeof e.contents=="string"?e.contents:"";if(await f.promises.readFile(a,"utf8")===E){i(n,"INFO","File content has no changes, skipping write",{filePath:t});break}await f.promises.writeFile(a,E,"utf8"),i(n,"INFO","File modified successfully",{filePath:t});break}default:{i(n,"WARN","Unsupported operation type",{operation:c,filePath:t});break}}}return i(n,"INFO","User files updated successfully",{userId:r,cId:o,filesCount:s.length,elapsedMs:Date.now()-l}),{success:!0,message:"User files updated successfully",userId:r,cId:o,filesCount:s.length}}catch(e){throw i(n,"ERROR","User files updated failed",{userId:r,cId:o,error:e.message,elapsedMs:Date.now()-l}),new P(`User files updated failed: ${e.message}`,{userId:r,cId:o,originalError:e.message})}}async function N(d,m,s,l){const n=Date.now(),w=`computer:${d}:${m}`,r=I.COMPUTER_WORKSPACE_DIR;if(!d)throw new g("userId cannot be empty",{field:"userId"});if(!m)throw new g("cId cannot be empty",{field:"cId"});if(!s)throw new g("file cannot be empty",{field:"file"});if(!l||typeof l!="string")throw new g("filePath cannot be empty",{field:"filePath"});const o=String(d),u=String(m),e=h.join(r,o,u);f.existsSync(e)||f.mkdirSync(e,{recursive:!0});const c=h.normalize(l).replace(/^[\/\\]+/,""),p=h.join(e,c),t=h.resolve(p),a=h.resolve(e);if(!t.startsWith(a+h.sep)&&t!==a)throw new g("File path is not secure, cannot exceed user directory",{field:"filePath",providedPath:l,resolvedPath:t});try{if(await f.promises.mkdir(h.dirname(p),{recursive:!0}),s.buffer)await f.promises.writeFile(p,s.buffer);else if(typeof s.contents=="string")await f.promises.writeFile(p,s.contents,"utf8");else throw new g("File content format is incorrect",{field:"file",hasBuffer:!!s.buffer,hasContents:typeof s.contents});return i(w,"INFO","File uploaded successfully",{userId:o,cId:u,filePath:c,targetPath:t,fileSize:s.buffer?s.buffer.length:s.contents?s.contents.length:0,elapsedMs:Date.now()-n}),{success:!0,message:"File uploaded successfully",fileSize:s.buffer?s.buffer.length:s.contents?s.contents.length:0}}catch(y){throw i(w,"ERROR","File upload failed",{userId:o,cId:u,filePath:c,error:y.message,elapsedMs:Date.now()-n}),new P(`File upload failed: ${y.message}`,{userId:o,cId:u,filePath:c,originalError:y.message})}}async function z(d,m,s,l){const n=Date.now(),w=`computer:${d}:${m}`;if(!d)throw new g("userId cannot be empty",{field:"userId"});if(!m)throw new g("cId cannot be empty",{field:"cId"});if(!Array.isArray(s))throw new g("files must be an array",{field:"files"});if(!Array.isArray(l))throw new g("filePaths must be an array",{field:"filePaths"});if(s.length!==l.length)throw new g(`File count (${s.length}) does not match path count (${l.length})`,{field:"filePaths"});i(w,"DEBUG","Start batch uploading files",{userId:d,cId:m,filesCount:s.length});const r=[];try{for(let e=0;e<s.length;e++){const c=s[e],p=l[e];if(!c){i(w,"WARN","Empty file object encountered in batch upload, skipping",{index:e,filePath:p}),r.push({success:!1,filePath:p,error:"Empty file object"});continue}if(!p||typeof p!="string"){i(w,"WARN","Invalid file path in batch upload, skipping",{index:e,originalname:c.originalname}),r.push({success:!1,filePath:p||"",originalname:c.originalname,error:"Invalid file path"});continue}try{const t=await N(d,m,c,p);r.push({success:!0,filePath:p,originalname:c.originalname,...t})}catch(t){i(w,"ERROR","Single file upload failed in batch upload",{filePath:p,originalname:c.originalname,error:t.message}),r.push({success:!1,filePath:p,originalname:c.originalname,error:t.message})}}const o=r.filter(e=>e.success).length,u=r.filter(e=>!e.success).length;return i(w,"INFO","Batch upload files completed",{userId:d,cId:m,totalCount:s.length,successCount:o,failCount:u,elapsedMs:Date.now()-n}),{success:!0,message:"Batch upload completed",totalCount:s.length,successCount:o,failCount:u,results:r}}catch(o){throw i(w,"ERROR","Batch upload files failed",{userId:d,cId:m,error:o.message,elapsedMs:Date.now()-n}),new P(`Batch upload files failed: ${o.message}`,{userId:d,cId:m,originalError:o.message})}}async function v(d,m){const s=Date.now(),l=`computer:${d}:${m}`,n=I.COMPUTER_WORKSPACE_DIR;if(!d)throw new g("userId cannot be empty",{field:"userId"});if(!m)throw new g("cId cannot be empty",{field:"cId"});if(!n)throw new P("COMPUTER_WORKSPACE_DIR is not configured, cannot create zip");const w=String(d),r=String(m),o=h.join(n,w,r);if(!f.existsSync(o)){const t=`${w}_${r}.zip`;i(l,"WARN","Workspace directory does not exist, returning empty zip",{targetDir:o,userId:w,cId:r,zipFileName:t});const a=S("zip",{zlib:{level:9}});return a.append(null,{name:`${w}_${r}/`,type:"directory"}),a.on("warning",y=>{if(y.code==="ENOENT")i(l,"WARN","Encountered file problem when creating empty zip",{message:y.message,code:y.code});else throw i(l,"ERROR","Encountered warning when creating empty zip",{message:y.message,code:y.code}),y}),a.on("error",y=>{i(l,"ERROR","Failed to create empty zip",{message:y.message})}),{archive:a,zipFileName:t}}const u=`${w}_${r}.zip`;i(l,"DEBUG","Start creating workspace directory zip",{targetDir:o,zipFileName:u});const e=S("zip",{zlib:{level:9}}),c=I.CONTENT_TRAVERSE_EXCLUDE_FILES||[],p=I.TRAVERSE_EXCLUDE_DIRS||[];return e.directory(o,`${w}_${r}`,t=>{const a=t.name||"",y=a.split(/[\/\\]/).filter(Boolean);if(y.some(R=>R.startsWith(".")))return!1;const F=y[y.length-1];if(c.includes(F)||y.some(R=>p.includes(R)))return!1;try{const R=h.join(o,a),E=f.lstatSync(R);if(E.isSymbolicLink()||E.nlink>1)return!1}catch(R){return i(l,"WARN","Error occurred when detecting link file, skipping",{filePath:a,error:R.message}),!1}return t}),e.on("warning",t=>{if(t.code==="ENOENT")i(l,"WARN","Encountered file problem when creating zip",{message:t.message,code:t.code});else throw i(l,"ERROR","Encountered warning when creating zip",{message:t.message,code:t.code}),t}),e.on("error",t=>{i(l,"ERROR","Failed to create zip",{message:t.message,elapsedMs:Date.now()-s})}),e.on("end",()=>{i(l,"INFO","Workspace directory zip created successfully",{targetDir:o,zipFileName:u,elapsedMs:Date.now()-s})}),{archive:e,zipFileName:u}}export{O as getFileList,$ as updateFiles,N as uploadFile,z as uploadFiles,v as downloadAllFiles};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import e from"fs";import a from"path";import M from"../../appConfig/index.js";import{extractZip as W}from"../common/zipUtils.js";import{ValidationError as g,SystemError as j,FileError as _}from"../error/errorHandler.js";import{log as o}from"../log/logUtils.js";async function A(t="computer"){const i=M.COMPUTER_WORKSPACE_DIR;if(!i)throw new g("COMPUTER_WORKSPACE_DIR configuration does not exist",{field:"COMPUTER_WORKSPACE_DIR"});return e.existsSync(i)||(await e.promises.mkdir(i,{recursive:!0}),o(t,"INFO","Created user workspace root directory",{workspaceRoot:i})),i}async function v(t,i){const r=a.join(t,i);if(e.existsSync(r)&&(await e.promises.lstat(r)).isDirectory())return r;const y=await e.promises.readdir(t,{withFileTypes:!0});for(const s of y){if(!s.isDirectory())continue;const f=a.join(t,s.name),w=a.join(f,i);if(e.existsSync(w)&&(await e.promises.lstat(w)).isDirectory())return w}return null}async function V(t){return v(t,"skills")}const $=".dynamic_add.lock";function C(t){const i=a.join(t,$);return e.existsSync(i)&&e.statSync(i).isFile()}async function D(t){e.existsSync(t)&&await e.promises.rm(t,{recursive:!0,force:!0})}async function R(t,i){try{await e.promises.rename(t,i)}catch(r){if(r.code==="EXDEV"){async function y(s,f){if((await e.promises.lstat(s)).isDirectory()){await e.promises.mkdir(f,{recursive:!0});const S=await e.promises.readdir(s);for(const k of S)await y(a.join(s,k),a.join(f,k))}else await e.promises.copyFile(s,f)}await y(t,i),await e.promises.rm(t,{recursive:!0,force:!0})}else throw r}}async function T(t,i,r){const y=Date.now(),s=`computer:${t}:${i}`;if(!t)throw new g("userId cannot be empty",{field:"userId"});if(!i)throw new g("cId cannot be empty",{field:"cId"});const f=await A(s),w=a.join(f,String(t),String(i),".tmp"),S=a.join(f,String(t),String(i)),k=a.join(S,".claude"),d=a.join(k,"skills"),x=a.join(k,"agents");e.existsSync(S)||await e.promises.mkdir(S,{recursive:!0}),e.existsSync(k)||await e.promises.mkdir(k,{recursive:!0});const u=a.join(w,`preserved_skills_${Date.now()}_${Math.round(Math.random()*1e6)}`);if(e.existsSync(d)){const l=(await e.promises.readdir(d,{withFileTypes:!0})).filter(p=>p.isDirectory()&&C(a.join(d,p.name)));if(l.length>0){await e.promises.mkdir(u,{recursive:!0});for(const p of l){const h=a.join(d,p.name),F=a.join(u,p.name);await R(h,F)}o(s,"INFO","\u4FDD\u7559\u542B .dynamic_add.lock \u7684 skill",{preserved:l.map(p=>p.name)})}}if(await D(d),await D(x),e.existsSync(u)){await e.promises.mkdir(d,{recursive:!0});const n=await e.promises.readdir(u,{withFileTypes:!0});for(const l of n)if(l.isDirectory()){const p=a.join(u,l.name),h=a.join(d,l.name);await R(p,h)}await D(u)}const m=e.existsSync(d),N=e.existsSync(x);if(o(s,"INFO","Deleted old skills and agents directories completed",{userId:t,cId:i,targetSkillsDir:d,targetAgentsDir:x,skillsExists:m,agentsExists:N}),!r)return o(s,"INFO","Created workspace (no uploaded file, no skills and agents)",{userId:t,cId:i,workspaceRoot:f,claudeDir:k,skillsDir:null,agentsDir:null,elapsedMs:Date.now()-y}),{message:"Workspace created (no uploaded file, no skills and agents)",workspaceRoot:f};if(!r.path)throw new g("Uploaded file has no valid path",{field:"file.path"});if(a.extname(r.originalname||r.filename||"").toLowerCase()!==".zip")throw new g("Only zip files are supported",{field:"file",originalName:r.originalname});o(s,"DEBUG","Start processing uploaded zip file",{userId:t,cId:i,workspaceRoot:f,tempZipPath:r.path});const c=a.join(w,`skill_extract_${Date.now()}_${Math.round(Math.random()*1e6)}`);try{e.existsSync(w)||await e.promises.mkdir(w,{recursive:!0}),await e.promises.mkdir(c,{recursive:!0}),o(s,"DEBUG","Start extracting zip file",{extractRoot:c}),await W(r.path,c),o(s,"DEBUG","Zip file extracted successfully",{extractRoot:c});const n=await v(c,"skills"),l=await v(c,"agents"),p=[];if(n){await e.promises.mkdir(d,{recursive:!0});const F=await e.promises.readdir(n,{withFileTypes:!0});for(const z of F){if(!z.isDirectory())continue;const P=a.join(n,z.name),O=a.join(d,z.name);e.existsSync(O)&&await D(O),await R(P,O)}p.push("skills"),o(s,"INFO","skills updated to workspace",{userId:t,cId:i,workspaceRoot:f,claudeDir:k,targetSkillsDir:d})}else o(s,"INFO","skills directory not found in zip, skipping",{userId:t,cId:i,extractRoot:c});l?(await R(l,x),p.push("agents"),o(s,"INFO","agents updated to workspace",{userId:t,cId:i,workspaceRoot:f,claudeDir:k,targetAgentsDir:x})):o(s,"INFO","agents directory not found in zip, skipping",{userId:t,cId:i,extractRoot:c}),p.length===0&&o(s,"WARN","skills and agents directories not found in zip",{userId:t,cId:i,extractRoot:c});const h=p.length>0?`Workspace created successfully, ${p.join(" and ")} updated`:"Workspace created successfully (skills and agents directories not found in zip)";return o(s,"INFO",h,{userId:t,cId:i,updatedDirs:p,elapsedMs:Date.now()-y}),{message:h,workspaceRoot:f}}catch(n){throw o(s,"ERROR","Failed to process uploaded zip file",{userId:t,cId:i,error:n.message,elapsedMs:Date.now()-y}),n instanceof g||n instanceof _||n instanceof j?n:new j(`Failed to create workspace: ${n.message}`,{userId:t,cId:i})}finally{try{e.existsSync(c)&&await e.promises.rm(c,{recursive:!0,force:!0})}catch(n){o(s,"WARN","Failed to clean up temporary extracted zip",{extractRoot:c,error:n.message})}try{r&&r.path&&e.existsSync(r.path)&&await e.promises.unlink(r.path)}catch(n){o(s,"WARN","Failed to clean up uploaded zip file",{tempZipPath:r?.path,error:n.message})}}}async function U(t,i,r){const y=Date.now(),s=`computer:${t}:${i}`;if(!t)throw new g("userId cannot be empty",{field:"userId"});if(!i)throw new g("cId cannot be empty",{field:"cId"});if(!r||!r.path)throw new g("Uploaded file has no valid path",{field:"file.path"});if(a.extname(r.originalname||r.filename||"").toLowerCase()!==".zip")throw new g("Only zip files are supported",{field:"file",originalName:r?.originalname});const w=await A(s),S=a.join(w,String(t),String(i),".tmp"),k=a.join(w,String(t),String(i)),d=a.join(k,".claude"),x=a.join(d,"skills"),u=a.join(S,`skill_push_${Date.now()}_${Math.round(Math.random()*1e6)}`);try{e.existsSync(k)||await e.promises.mkdir(k,{recursive:!0}),e.existsSync(d)||await e.promises.mkdir(d,{recursive:!0}),e.existsSync(x)||await e.promises.mkdir(x,{recursive:!0}),e.existsSync(S)||await e.promises.mkdir(S,{recursive:!0}),await e.promises.mkdir(u,{recursive:!0}),o(s,"DEBUG","Start extracting skill zip file",{extractRoot:u}),await W(r.path,u),o(s,"DEBUG","Skill zip file extracted successfully",{extractRoot:u});const m=await v(u,"skills");if(!m)return o(s,"WARN","skills directory not found in zip",{userId:t,cId:i,extractRoot:u}),{message:"skills directory not found in zip",workspaceRoot:w,updatedSkills:[]};const E=(await e.promises.readdir(m,{withFileTypes:!0})).filter(l=>l.isDirectory()&&!l.name.startsWith("."));if(E.length===0)return o(s,"WARN","skills directory in zip has no skill subdirectories",{userId:t,cId:i,skillsDir:m}),{message:"skills directory in zip has no skill subdirectories",workspaceRoot:w,updatedSkills:[]};const c=[];for(const l of E){const p=a.join(m,l.name),h=a.join(x,l.name);e.existsSync(h)&&await D(h),await R(p,h),c.push(l.name),o(s,"INFO","skill pushed to workspace",{userId:t,cId:i,skillName:l.name,destSkillPath:h})}const n=c.length>0?`Pushed ${c.length} skills: ${c.join(", ")}`:"skills directory not found in zip";return o(s,"INFO",n,{userId:t,cId:i,updatedSkills:c,elapsedMs:Date.now()-y}),{message:n,workspaceRoot:w,updatedSkills:c}}catch(m){throw o(s,"ERROR","Failed to push skill to workspace",{userId:t,cId:i,error:m.message,elapsedMs:Date.now()-y}),m instanceof g||m instanceof _||m instanceof j?m:new j(`Failed to push skill to workspace: ${m.message}`,{userId:t,cId:i})}finally{try{e.existsSync(u)&&await e.promises.rm(u,{recursive:!0,force:!0})}catch(m){o(s,"WARN","Failed to clean up temporary extracted zip",{extractRoot:u,error:m.message})}try{r&&r.path&&e.existsSync(r.path)&&await e.promises.unlink(r.path)}catch(m){o(s,"WARN","Failed to clean up uploaded zip file",{tempZipPath:r?.path,error:m.message})}}}export{T as createWorkspace,U as pushSkillsToWorkspace};
|
package/dist/utils/envUtils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import m from"path";import d from"fs-extra";import g from"dotenv";function E(){return process.platform==="win32"}function u(e){return E()?e.toUpperCase():e}function v(e,o=void 0){const n=u(e);return process.env[n]!==void 0?process.env[n]:e!==n&&process.env[e]!==void 0?process.env[e]:o}function $(e,o=!1){const n=v(e);if(n===void 0)return o;const r=String(n).toLowerCase();return r==="true"||r==="1"||r==="yes"}function b(e,o=void 0){const n=v(e);if(n===void 0)return o;const r=Number(n);return Number.isNaN(r)?(console.warn(`Environment variable ${e} value "${n}" is not a valid number`),o):r}function N(e){if(!e)return"production";const o=e.toLowerCase().trim();return{dev:"development",test:"test",prod:"production",production:"production",development:"development",staging:"staging"}[o]||"production"}function O(e,o={}){const n=o.basePath||process.cwd(),r=N(e),s=[`.env.${r}`,`.env.${r}.local`,".env.local",".env"],t=[],l={loaded:!1,files:t,env:r};for(const i of s){const a=m.join(n,i);if(d.existsSync(a))try{const c=g.config({path:a,override:!1});c.error?console.warn(`Load environment file ${i} failed: ${c.error.message}`):(t.push(a),l.loaded=!0)}catch(c){console.warn(`Load environment file ${i} failed: ${c.message}`)}}return t.length>0&&console.log(`Loaded environment files: ${t.join(", ")}`),l}function h(e){const o={loaded:!1,path:e,data:{}};if(!e)return o;if(!d.existsSync(e))return console.warn(`Configuration file does not exist: ${e}`),o;try{const n=m.extname(e).toLowerCase();if(n===".json"){const r=d.readFileSync(e,"utf8");o.data=JSON.parse(r),o.loaded=!0}else if(n===".env"||n===""){const r=g.config({path:e,override:!0});r.error||(o.loaded=!0,Object.keys(r.parsed||{}).forEach(s=>{o.data[s]=process.env[s]}))}else console.warn(`\u4E0D\u652F\u6301\u7684\u914D\u7F6E\u6587\u4EF6\u683C\u5F0F: ${n}`);console.log(`Loaded configuration file: ${e}`)}catch(n){console.error(`Load configuration file failed: ${n.message}`)}return o}function y(){const e={},o=process.argv.slice(2);for(let n=0;n<o.length;n++){const r=o[n];if(r.startsWith("--")){let s=r.slice(2),t=null;if(s.includes("=")){const i=s.split("=");s=i[0],t=i.slice(1).join("=")}else n+1<o.length&&!o[n+1].startsWith("--")?(t=o[n+1],n++):t="true";["env","port","config","force","help","version"].includes(s)||(e[u(s)]=t)}}return e}function C(e={}){const{env:o,config:n,port:r,basePath:s}=e,t=O(o,{basePath:s}),l=h(n),i=t.env;process.env.NODE_ENV=i,r&&(process.env.PORT=String(r)),l.loaded&&Object.entries(l.data).forEach(([c,f])=>{const p=u(c);process.env[p]===void 0&&(process.env[p]=f)});const a=y();return Object.entries(a).forEach(([c,f])=>{process.env[c]=f}),{env:i,port:process.env.PORT,config:l.loaded?l.path:null,files:t.files}}function w(){const e={env:process.env.NODE_ENV||"unknown",port:process.env.PORT||"default",platform:process.platform,nodeVersion:process.version};return JSON.stringify(e,null,2)}export{E as isWindows,u as normalizeEnvName,v as getEnv,$ as getBoolEnv,b as getNumberEnv,N as parseEnvType,O as loadEnvFile,h as loadCustomConfigFile,y as loadEnvFromArgv,C as applyEnv,w as createEnvSummary};process.argv[1]&&import.meta.url.endsWith(process.argv[1].replace(/\\/g,"/").replace(/^.*[\/\\]/,""))&&(console.log(`
|
|
2
|
+
Current environment configuration:
|
|
3
3
|
`),console.log(w()),console.log(`
|
|
4
|
-
|
|
4
|
+
Detailed environment variables:
|
|
5
5
|
`),console.log("NODE_ENV:",process.env.NODE_ENV),console.log("PORT:",process.env.PORT),console.log("CONFIG_FILE:",process.env.CONFIG_FILE),console.log(""));
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import{log as l}from"../log/logUtils.js";import c from"path";import{sanitizeSensitivePaths as
|
|
2
|
-
`);for(const
|
|
3
|
-
`),e={before:[],error:null,after:[]};let
|
|
1
|
+
import{log as l}from"../log/logUtils.js";import c from"path";import{sanitizeSensitivePaths as m}from"../common/sensitiveUtils.js";class u{constructor(){this.errorPatterns=[{name:"Regular expression HTML tag escape error",pattern:/html\.match\(\/<title>\(\.\*\?\)<\/title>\/i\)/,suggestion:"In regular expressions, the angle brackets of HTML tags need to be escaped. Please modify `</title>` to `</title>`",example:{wrong:"html.match(/<title>(.*?)</title>/i)",correct:"html.match(/<title>(.*?)<\\/title>/i)"}},{name:"JavaScript syntax error",pattern:/Parse error|SyntaxError|Unexpected token/,suggestion:"Check the code syntax, ensure that the parentheses, quotes, semicolons, etc. are correctly paired",example:null},{name:"Module import error",pattern:/Cannot resolve module|Module not found/,suggestion:"Check the import path to ensure that the module file exists",example:null},{name:"TypeScript type error",pattern:/Type error|Type '.*' is not assignable/,suggestion:"Check the variable type definition, ensure that the type matches",example:null},{name:"Dependency missing error",pattern:/Cannot find module|Module not found/,suggestion:"Run `pnpm install` to install the missing dependency package",example:null}]}parseBuildError(n,r){try{l(r,"INFO","Start parsing build error",{errorMessage:n});const e=this.extractFileInfo(n),o=this.extractErrorDetails(n),t=this.getErrorSuggestions(n),i=this.generateUserFriendlyMessage(o,e,t,n);return l(r,"INFO","Build error parsing completed",{errorType:o.type,fileName:e?.path?c.basename(e.path):null,suggestionsCount:t.length}),i}catch(e){return l(r,"ERROR","Exception occurred when parsing build error",{error:e.message,stack:e.stack}),"Build failed, please check the detailed error information in the build log, or contact technical support."}}extractFileInfo(n){const r=n.match(/file:\s*([^\n]+):(\d+):(\d+)/);if(!r)return null;const[,e,o,t]=r;return{path:e.trim(),line:parseInt(o),column:parseInt(t),relativePath:this.getRelativePath(e.trim())}}extractErrorDetails(n){const r=n.match(/(Parse error|SyntaxError|TypeError|ReferenceError|Unexpected token)/),e=r?r[1]:"Build error";let o=n;const t=n.match(/(?:Parse error|SyntaxError|TypeError|ReferenceError)[^:]*:\s*([^\n]+)/);if(t)o=t[1].trim();else{const i=n.split(`
|
|
2
|
+
`);for(const a of i)if(a.trim()&&!a.includes("file:")&&!a.includes("at ")){o=a.trim();break}}return{type:e,message:o}}getErrorSuggestions(n){const r=[];for(const o of this.errorPatterns)o.pattern.test(n)&&r.push({type:o.name,message:o.suggestion,priority:"high",example:o.example});r.length===0&&r.push({type:"General suggestion",message:"Please carefully check the files and line numbers mentioned in the error information, ensure that the code syntax is correct",priority:"medium"});const e=this.extractFileInfo(n);if(e){const o=c.basename(e.path);r.push({type:"File check",message:`Please check the code near line ${e.line} column ${e.column} in file ${o}`,priority:"high"})}return r}extractCodeContext(n){const r=n.split(`
|
|
3
|
+
`),e={before:[],error:null,after:[]};let o=!1,t=0;for(let i=0;i<r.length;i++){const a=r[i],p=a.match(/^\s*(\d+):\s*(.*)$/);if(p){const[,s,h]=p;t=parseInt(s),o?e.after.push({line:t,content:h.trim()}):e.before.push({line:t,content:h.trim()})}if(a.includes("^")&&!o&&(o=!0,e.before.length>0)){const s=e.before.pop();e.error=s}}return e.before=e.before.slice(-3),e.after=e.after.slice(0,3),e.before.length>0||e.error||e.after.length>0?e:null}getRelativePath(n){const r=this.sanitizePath(n),e=r.match(/project_workspace\/[^\/]+\/(.+)$/);if(e)return e[1];const o=r.split("/");return o[o.length-1]}sanitizePath(n){return m(n)}generateUserFriendlyMessage(n,r,e,o){let t=`Build failed!
|
|
4
4
|
|
|
5
|
-
`;if(t
|
|
6
|
-
`,t
|
|
5
|
+
`;if(t+=`Error type: ${n.type}
|
|
6
|
+
`,t+=`Error description: ${n.message}
|
|
7
7
|
|
|
8
|
-
`,r){const
|
|
9
|
-
`,t+=`
|
|
10
|
-
`,t+=`
|
|
8
|
+
`,r){const i=c.basename(r.path);t+=`\u{1F4CD} Error location:
|
|
9
|
+
`,t+=` File: ${i}
|
|
10
|
+
`,t+=` Line: ${r.line}, Column: ${r.column}
|
|
11
11
|
|
|
12
|
-
`}return e.length>0&&(t+=`\u{1F527}
|
|
13
|
-
`,e.forEach((a
|
|
14
|
-
`,
|
|
15
|
-
`,t+=`
|
|
12
|
+
`}return e.length>0&&(t+=`\u{1F527} Repair suggestions:
|
|
13
|
+
`,e.forEach((i,a)=>{t+=` ${a+1}. ${i.message}
|
|
14
|
+
`,i.example&&(t+=` Wrong code: ${i.example.wrong}
|
|
15
|
+
`,t+=` Correct code: ${i.example.correct}
|
|
16
16
|
`)}),t+=`
|
|
17
|
-
`),t+=`\u{1F4A1}
|
|
18
|
-
`,t+=` 1.
|
|
19
|
-
`,t+=` 2.
|
|
20
|
-
`,t+=` 3.
|
|
17
|
+
`),t+=`\u{1F4A1} Operation steps:
|
|
18
|
+
`,t+=` 1. Please modify the code according to the above suggestions
|
|
19
|
+
`,t+=` 2. Save the file and rebuild the project
|
|
20
|
+
`,t+=` 3. If the problem still exists, please check other related files
|
|
21
21
|
|
|
22
|
-
`,t+=`\u{1F4DE}
|
|
23
|
-
`,t+="
|
|
22
|
+
`,t+=`\u{1F4DE} Need help?
|
|
23
|
+
`,t+=" If you cannot solve this problem, please contact technical support and provide complete error information.",t}}export default u;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{log as
|
|
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
|
|
2
|
-
`),h.isEnabled()&&!h.set(String(
|
|
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
|
|
2
|
-
`);return this.cache.set(
|
|
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
|
|
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]
|
|
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};
|