rtjscomp 0.9.3 → 0.9.4
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/package.json +1 -2
- package/rtjscomp.js +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rtjscomp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "php-like server but with javascript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"url": "https://github.com/L3P3/rtjscomp/issues"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"google-closure-compiler": "^20240317.0.0",
|
|
14
13
|
"ipware": "latest",
|
|
15
14
|
"parse-multipart-data": "latest",
|
|
16
15
|
"querystring": "latest"
|
package/rtjscomp.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
(async()=>{const D=require("fs"),E=require("fs/promises"),wa=require("http"),Oa=require("url"),Pa=require("zlib"),Qa=require("parse-multipart-data").parse,ea=require("querystring").decode,Ra=require("ipware")().get_ip,Sa=/bot|googlebot|crawler|spider|robot|crawling|favicon/i,Ta=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i,
|
|
6
6
|
xa={level:9},Ua=/,\s*/,fa=/\bimport\(/g;var z="undefined"!==typeof Bun;const Va=/:([0-9]+)[\):]/,ya={paths:[require("path").resolve()]},Wa=/\bservice_require\(([^)]*)\)/g,ha={persistent:!0,interval:1E3},za=process.argv.includes("-v");let r=za,N=0,O=0,Aa=!0,P=!1;const X=new Map([["","index.html"]]),Q=new Map([["index.html","/"]]),R=new Map,ia=new Set,ja=new Set,ka=new Set,la=new Set(["events","html","json","txt"]),ma=new Map([["apk","application/zip"],["bpg","image/bpg"],["css","text/css; charset=utf-8"],
|
|
7
7
|
["events","text/event-stream"],["flac","audio/flac"],["gz","application/gzip"],["hta","application/hta"],["html","text/html; charset=utf-8"],["ico","image/x-icon"],["jpg","image/jpeg"],["js","text/javascript; charset=utf-8"],["json","application/json; charset=utf-8"],["mid","audio/midi"],["mp3","audio/mpeg3"],["pdf","application/pdf"],["png","image/png"],["rss","application/rss+xml; charset=utf-8"],["txt","text/plain; charset=utf-8"],["xml","application/xml; charset=utf-8"],["xz","application/x-xz"],
|
|
8
|
-
["zip","application/zip"]]),na=new Set("apk bpg flac gz jpg mp3 pdf png xz zip".split(" ")),Y=new Map,m={},A=global.rtjscomp={actions:m,version:"0.9.
|
|
8
|
+
["zip","application/zip"]]),na=new Set("apk bpg flac gz jpg mp3 pdf png xz zip".split(" ")),Y=new Map,m={},A=global.rtjscomp={actions:m,version:"0.9.4"};Object.fromEntries||(Object.fromEntries=a=>{const b={};for(const c of a)b[c[0]]=c[1];return b});let S=D.watch;if(z){const a=S,b=new Map;S=(c,h,n)=>{b.has(c)||a(c,h,()=>{const k=b.get(c);k&&k()});b.set(c,n);return{close:()=>b.set(c,null)}}}global.globals=A;global.actions=A.actions;global.data_load=a=>{d("[deprecated] synchronous load file: data/"+
|
|
9
9
|
a);try{return D.readFileSync("data/"+a,"utf8")}catch(b){return null}};global.data_save=(a,b)=>(d("[deprecated] synchronous save file: data/"+a),D.writeFileSync("data/"+a,b,"utf8"));global.number_check_int=a=>Math.floor(a)===a;global.number_check_uint=a=>0<=a&&number_check_int(a);A.data_load=async a=>{r&&d("load file: data/"+a);const b=await E.readFile("data/"+a,"utf8").catch(()=>null);return a.endsWith(".json")?JSON.parse(b||null):b};A.data_load_watch=(a,b)=>oa("data/"+a,c=>b(a.endsWith(".json")?
|
|
10
10
|
JSON.parse(c||null):c));A.data_save=(a,b)=>(r&&d("save file: data/"+a),E.writeFile("data/"+a,a.endsWith(".json")?JSON.stringify(b):b,"utf8"));const Ba=a=>{try{return`:${a.stack.split("\n",2)[1].split(",").pop().match(Va)[1]-2}`}catch(b){return""}},Ca=new Set,pa=new Map,qa=new Map,ra=a=>{var b=pa.get(a);if(null!=b)return b;r&&d("require module: "+a);b=require.resolve(a,ya);Ca.add(b);pa.set(a,b=require(b));return b},sa=async a=>{let b=qa.get(a);if(null!=b)return b;r&&d("import module: "+a);qa.set(a,
|
|
11
11
|
b=await import("file://"+require.resolve(a,ya)));return b};m.module_cache_clear=()=>{for(const a of Ca)delete require.cache[a];pa.clear();qa.clear()};const ta=sa.constructor,F=new Map;let T=null,ua=null;const Xa=async a=>{await Promise.all([...F.values()].filter(c=>4>c.status&&!a.includes(c.path)).map(c=>(c.dependencies=null,c)).map(Da));const b=[];for(const c of a){let h=F.get(c);if(null==h)F.set(c,h={content:null,dependencies:null,x0:null,x1:null,x2:null,path:c,x5:null,x4:null,x7:null,
|
|
@@ -19,7 +19,7 @@ a),b()))},oa=async(a,b)=>{try{const h=await E.readFile(a,"utf8");r&&d("load file
|
|
|
19
19
|
delete a[b];return c},L=(a,b)=>{if(null===a||!(b in a))return null;const c=a[b];if("object"!==typeof c||!c||null==c.length||c.some(h=>"string"!==typeof h))throw b+" must be array of strings";delete a[b];return c},Ia=(a,b)=>{if(null===a||!(b in a))return null;let c=a[b];if("object"!==typeof c||!c||(c=Object.entries(c)).some(([,h])=>"string"!==typeof h))throw b+" must be object of strings";delete a[b];return c};var I=a=>a.split("\n").filter(b=>0<b.length&&35!==b.charCodeAt(0));const Ja=a=>Object.fromEntries(a.split("\n").filter(b=>
|
|
20
20
|
0<b.length&&35!==b.charCodeAt(0)).map(b=>b.split(":"))),M=(a,b=!1)=>{if(!b&&!a)throw"path is empty";if(47===a.charCodeAt(0))throw"path must not start with /";if(47===a.charCodeAt(a.length-1))throw"path must not end with /";if(a.includes(".."))throw"path must not contain ..";if(a.includes("~"))throw"path must not contain ~";if(a.includes("//"))throw"path must not contain //";};let Ka=A.log_history=[];m.log_clear=()=>{Ka=A.log_history=[]};const d=A.log=a=>(console.log(a),Ka.push(a),U?aa("log",[a]):
|
|
21
21
|
void 0),U=D.existsSync("spam.csv");A.spam_history="";m.spam_save=async(a=!1)=>{if(U)try{const b=A.spam_history;A.spam_history="";await E.appendFile("spam.csv",b,"utf8");r&&!a&&d("spam.csv saved")}catch(b){d("[error] cannot save spam.csv: "+b.message)}};const aa=(a,b)=>{A.spam_history+=Date.now()+","+a+","+JSON.stringify(b)+"\n";1E5<=A.spam_history.length&&m.spam_save()},La=async(a,b,c)=>{const h=a.method,n=a.headers,k=Ra(a).clientIp;"x-forwarded-proto"in n&&(c="https"===n["x-forwarded-proto"]);U&&
|
|
22
|
-
aa("request",[c,a.url,k]);try{const x=Oa.parse(a.url,!1);let e=x.pathname||"/";if(47!==e.charCodeAt(0)||e.includes("//"))throw 404;if(1<e.length&&e.endsWith("/")&&(e=e.slice(0,-1),e.lastIndexOf("/")<e.lastIndexOf(".")))throw b.setHeader("Location",e),301;e=e.slice(1);if(!(e.includes("php")||e.includes("sql")||e.includes(".git/")||ia.has(e))){b.setHeader("Server","l3p3 rtjscomp v0.9.
|
|
22
|
+
aa("request",[c,a.url,k]);try{const x=Oa.parse(a.url,!1);let e=x.pathname||"/";if(47!==e.charCodeAt(0)||e.includes("//"))throw 404;if(1<e.length&&e.endsWith("/")&&(e=e.slice(0,-1),e.lastIndexOf("/")<e.lastIndexOf(".")))throw b.setHeader("Location",e),301;e=e.slice(1);if(!(e.includes("php")||e.includes("sql")||e.includes(".git/")||ia.has(e))){b.setHeader("Server","l3p3 rtjscomp v0.9.4");b.setHeader("Access-Control-Allow-Origin","*");var g=null,t=null;if(Q.has(e))throw b.setHeader("Location",Q.get(e)),
|
|
23
23
|
301;if(X.has(e))e=X.get(e);else{var l=e.split("/"),q=R.get(l.shift());if(null!=q)a:for(var w of q){var G=w.x3,B=G.length;if(B===l.length){q={};for(let u=0;u<B;++u)if(42===G[u].charCodeAt(0))1<G[u].length&&(q[G[u].slice(1)]=l[u]);else if(G[u]!==l[u])continue a;e=w.value;g=q;break}}}var J=e.lastIndexOf(".");if(e.includes("..")||e.includes("~")||J<=e.lastIndexOf("/"))throw 404;var p=e.slice(J+1).toLowerCase(),y=Aa&&"accept-encoding"in n&&!na.has(p)&&n["accept-encoding"].split(Ua).includes("gzip"),H=
|
|
24
24
|
la.has(p)&&!ka.has(e);if("GET"!==h){if(!H)throw 405;"content-length"in n&&(t=new Promise(u=>{const C=[];a.on("data",v=>{C.push(v)});a.on("end",v=>{v&&C.push(v);u(Buffer.concat(C))})}))}l=J=null;w="public/"+e;if(H&&Y.has(e))J=Y.get(e);else{r&&d(`load ${H?"dynam":"stat"}ic file: ${e}`);if(ja.has(e)||e.endsWith(".service.js"))throw 403;if(!D.existsSync(w))throw 404;l=D.statSync(w);if(l.isDirectory())throw 403;if(H){const u=await E.readFile(w,"utf8");try{if(u.includes("\r"))throw"illegal line break, must be unix";
|
|
25
25
|
u.includes("globals.")&&d(`[deprecated] ${e}: uses globals object`);const C=u.length;let v=`const log=a=>rtjscomp.log(${JSON.stringify(e+": ")}+a);`;G=!1;for(q=B=0;q<C;)if(G){if(0>(q=u.indexOf("?>",B=q+2)))throw'"?>" missing';G=!1;B<q&&(v=61!==u.charCodeAt(B)?v+(u.slice(B,q).replace(fa,"custom_import(")+";"):v+`output.write(''+(${u.slice(++B,q).replace(fa,"custom_import(")}));`);q+=2}else-1<(q=u.indexOf("<?",B=q))?G=!0:q=C,B<q&&(v+=`output.write(${JSON.stringify(u.slice(B,q))});`);try{J=new ta("input",
|
|
@@ -30,7 +30,7 @@ f).map(f=>"object"!==typeof f[1]||f[1].length?f:[f[0],Object.keys(f[1]).slice(0,
|
|
|
30
30
|
v){b.headersSent?(null!=b.writableEnded?b.writableEnded:b.finished)||C.end(`${"html"===p?"<hr>":"\n\n---\n"}ERROR!`):y&&b.removeHeader("Content-Encoding");if("number"!==typeof v)throw d(`[error] ${e}: invalid return type: ${typeof v}`),500;if(b.headersSent&&500>v)throw d(`[error] ${e}: status code after content`),500;throw v;}C.end()}else c=null,y&&80<l.size&&D.existsSync(w+".gz")?c=D.createReadStream(w+".gz"):(y=!1,c=D.createReadStream(w)),U&&aa("static_send",[e,y]),b.setHeader("Cache-Control","public, max-age=600"),
|
|
31
31
|
y?b.setHeader("Content-Encoding","gzip"):b.setHeader("Content-Length",l.size),c.pipe(b)}}catch(x){"number"!==typeof x&&(console.error(x),x=500),(500<=x||r&&400<=x)&&d(`[error] request failed: ${x}; ${k}; ${a.url}`),b.headersSent||(b.writeHead(x,{"Content-Type":"text/html","Cache-Control":"no-cache, no-store"}),b.end(`<!DOCTYPE html><html><body><h1>HTTP ${x}: ${wa.STATUS_CODES[x]||"Error"}</h1></body></html>`))}};m.halt=async()=>{P=!0;r&&d("stop all");await Promise.all([m.http_stop&&m.http_stop(),
|
|
32
32
|
m.https_stop&&m.https_stop(),Ya()]);await m.spam_save();d("stopped all")};m.exit=async a=>{P||("number"!==typeof a&&(a=0),await m.halt(),r&&d("exit"),process.exit(a))};process.on("uncaughtException",a=>{"symbol"===typeof a&&(a=a.toString());d("[error] uncaughtException: "+(a.message||a));console.error(a);P&&process.exit(1);m.exit(1)});process.on("unhandledRejection",a=>{d("[error] unhandledRejection: "+(a.message||a));console.error(a);P&&process.exit(1);m.exit(1)});process.on("exit",m.exit);process.on("SIGINT",
|
|
33
|
-
m.exit);process.on("SIGUSR2",m.exit);process.on("SIGTERM",m.exit);d(`rtjscomp v${"0.9.
|
|
33
|
+
m.exit);process.on("SIGUSR2",m.exit);process.on("SIGTERM",m.exit);d(`rtjscomp v${"0.9.4"} in ${z?"bun":"node"} on ${process.platform.replace("win32","windows")}`);await oa("config/init.js",async a=>{if(a){d("[deprecated] run global init script");try{await (new ta("require",a))(ra)}catch(b){d("[error] init.js: "+b.message)}}});const [bb,cb,...Ma]=await Promise.all([E.stat("data/").catch(a=>null),E.stat("public/").catch(a=>null),..."file_blocks file_privates file_raws file_type_dyns file_type_mimes file_type_nocompress path_aliases port_http port_https services".split(" ").map(a=>
|
|
34
34
|
E.readFile("config/"+a+".txt","utf8").catch(b=>null))]);bb||D.mkdirSync("data/");cb||D.cpSync(__dirname+"/public/","public/",{recursive:!0});if(Ma.some(a=>null!==a)){z=JSON.parse(await E.readFile("rtjscomp.json","utf8").catch(w=>null))||{};const [a,b,c,h,n,k,g,t,l,q]=Ma;a&&(z.path_ghosts=I(a));b&&(z.path_hiddens=I(b));c&&(z.path_statics=I(c));h&&(z.type_dynamics=I(h));n&&(z.type_mimes=Ja(n));k&&(z.type_raws=I(k));g&&(z.path_aliases=Ja(g));t&&(I=Number(t),isNaN(I)||(z.port_http=I));l&&(I=Number(l),
|
|
35
35
|
isNaN(I)||(z.port_https=I));q&&(z.services=q.split("\n").filter(w=>0<w.length));await E.writeFile("rtjscomp.json",JSON.stringify(z,null,"\t")+"\n","utf8");d("[deprecated] config files found, rtjscomp.json written, please delete config files")}let Na=0,ba=!1,W=null;const ca=new Map,da=wa.createServer((a,b)=>La(a,b,!1));da.on("error",a=>{d("[error] http: "+a.message);W&&W()});da.on("connection",a=>{const b=++Na;ca.set(b,a);a.on("close",()=>{ca.delete(b)})});m.http_start=async()=>{await m.http_stop();
|
|
36
36
|
N&&(ba=!0,d("start http: http://localhost:"+N),await new Promise(a=>da.listen(N,W=a)),W?W=null:r&&d("started http"))};m.http_stop=async()=>{if(ba){ba=!1;d("stop http");var a=setTimeout(m.http_kill,5E3);await new Promise(b=>da.close(b));clearTimeout(a);r&&d("stopped http")}};m.http_kill=async()=>{ba||(d("kill http"),await Promise.all([...ca.values()].map(a=>a.destroy())),r&&d("killed http"),ca.clear())};try{const a=D.readFileSync("config/ssl/domain.key"),b=D.readFileSync("config/ssl/chained.pem");
|