securequ 1.1.3 → 1.1.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/server/Base.d.ts CHANGED
@@ -1,25 +1,26 @@
1
1
  import Router from './Router.js';
2
- import { SecurequServerConfig, UploadFileMeta, HandlerInfo, ArgsInfo } from './types.js';
2
+ import { SecurequServerConfig, UploadFileMeta, HandlerInfo, Metadata } from './types.js';
3
3
 
4
- declare class SecurequServerBase extends Router {
5
- protected config: SecurequServerConfig;
6
- protected secret: string | null;
7
- protected clients: Map<string, string>;
8
- protected uploadMeta: Map<string, UploadFileMeta & {
9
- expire: number;
10
- }>;
11
- constructor(config: SecurequServerConfig);
12
- protected getSecret(): Promise<string>;
13
- protected clientInfo(path: string, origin: string): Promise<{
14
- path: string;
15
- secret: string;
16
- hash: string;
17
- searchParams: {
18
- [key: string]: any;
19
- };
20
- }>;
21
- protected isValidSigneture(signeture: string | undefined, hash: string): Promise<void>;
22
- handleRequest(info: HandlerInfo, args?: ArgsInfo): Promise<void>;
4
+ declare class SecurequServerBase extends Router {
5
+ protected config: SecurequServerConfig;
6
+ protected secret: string | null;
7
+ protected clients: Map<string, string>;
8
+ protected uploadMeta: Map<string, UploadFileMeta & {
9
+ expire: number;
10
+ }>;
11
+ readonly CONTENT_TYPE = "application/octet-stream";
12
+ constructor(config: SecurequServerConfig);
13
+ protected getSecret(): Promise<string>;
14
+ protected clientInfo(path: string, origin: string): Promise<{
15
+ path: string;
16
+ secret: string;
17
+ hash: string;
18
+ searchParams: {
19
+ [key: string]: any;
20
+ };
21
+ } | null>;
22
+ protected isValidSigneture(signeture: string | undefined, hash: string): Promise<void>;
23
+ handleRequest(info: HandlerInfo, metadata?: Metadata): Promise<void>;
23
24
  }
24
25
 
25
26
  export { SecurequServerBase as default };
package/server/Base.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../include/crypto.js"),t=require("./Router.js");class s extends t.default{constructor(e){if(super(),this.secret=null,this.clients=new Map,this.uploadMeta=new Map,!e.basepath)throw new Error("Basepath is required");if(!e.clients||0===Object.keys(e.clients).length)throw new Error("Atleast one client is required");e.basepath.startsWith("/")||(e.basepath=`/${e.basepath}`),e.basepath.endsWith("/")&&(e.basepath=e.basepath.substring(0,e.basepath.length-1)),e.upload&&(e.upload.maxFilesize=e.upload.maxFilesize||51200,e.upload.checkFileType=e.upload.checkFileType||!0),this.config=e;for(let e of this.config.clients)this.clients.set(e.origin,e.secret)}async getSecret(){return this.secret||(this.secret=await e.default.hash(Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15))),this.secret}async clientInfo(t,s){const a="/"!==t&&"development"===this.config.mode;let i=t.split("?");const n=(t=(t=(t=(t=i[0]).replace(this.config.basepath+"/","")).endsWith("/")?t.substring(0,t.length-1):t).startsWith("/")?t.substring(1):t).split("/"),r=n.shift();if(!(null==r?void 0:r.length)||!this.clients.has(s))throw new Response("Client not allowed",{status:403});let o=this.clients.get(s).substring(0,r.length),h={};return i.length>1&&(h=a?Object.fromEntries(new URLSearchParams(decodeURIComponent(i[1]))):await e.default.decrypt(decodeURIComponent(i[1]),o)),{path:"/"+n.join("/"),secret:o,hash:r,searchParams:h}}async isValidSigneture(t,s){const a=await this.getSecret();if(this.secret&&t){let i=await e.default.decrypt(t,a),n=i.hash===s,r=i.expire>Date.now();if(!n)throw new Response("Invalid Signeture",{status:403});if(!r)throw new Response("Signeture expired",{status:403})}}async handleRequest(e,t){if(this.config.accept){if(!await this.config.accept(e,t))throw new Response("Request not accepted",{status:403})}const{path:s,method:a}=e;let i=Object.values(this.routes[a]);for(let{test:a,handler:n}of i){const i=a(s);i&&await n(Object.assign(Object.assign({},e),{params:i.params}),t)}}}exports.default=s;//# sourceMappingURL=Base.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../include/crypto.js"),t=require("./Router.js");class s extends t.default{constructor(e){if(super(),this.secret=null,this.clients=new Map,this.uploadMeta=new Map,this.CONTENT_TYPE="application/octet-stream",!e.basepath)throw new Error("Basepath is required");if(!e.clients||0===Object.keys(e.clients).length)throw new Error("Atleast one client is required");e.basepath.startsWith("/")||(e.basepath=`/${e.basepath}`),e.basepath.endsWith("/")&&(e.basepath=e.basepath.substring(0,e.basepath.length-1)),e.upload&&(e.upload.maxFilesize=e.upload.maxFilesize||51200,e.upload.checkFileType=e.upload.checkFileType||!0),e.mode=["production","development"].includes(e.mode||"")?e.mode:"production",this.config=e;for(let e of this.config.clients)this.clients.set(e.origin,e.secret)}async getSecret(){return this.secret||(this.secret=await e.default.hash(Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15))),this.secret}async clientInfo(t,s){const i="/"!==t&&"development"===this.config.mode;let a=t.split("?");const n=(t=(t=(t=(t=a[0]).replace(this.config.basepath+"/","")).endsWith("/")?t.substring(0,t.length-1):t).startsWith("/")?t.substring(1):t).split("/"),r=n.shift();let o=this.clients.get(s);if(o||(o=this.clients.get("*")),!(null==r?void 0:r.length)||!o)return null;let c=o.substring(0,r.length),h={};return a.length>1&&(h=i?Object.fromEntries(new URLSearchParams(decodeURIComponent(a[1]))):await e.default.decrypt(decodeURIComponent(a[1]),c)),{path:"/"+n.join("/"),secret:c,hash:r,searchParams:h}}async isValidSigneture(t,s){const i=await this.getSecret();if(this.secret&&t){let a=await e.default.decrypt(t,i),n=a.hash===s,r=a.expire>Date.now();if(!n)throw new Response("Invalid Signeture",{status:403});if(!r)throw new Response("Signeture expired",{status:403})}}async handleRequest(e,t){if(this.config.accept){if(!await this.config.accept(e,t))throw new Response("Request not accepted",{status:403})}const{path:s,method:i}=e;let a=Object.values(this.routes[i]);for(let{test:i,handler:n}of a){const a=i(s);a&&await n(Object.assign(Object.assign({},e),{params:a.params}),t)}}}exports.default=s;//# sourceMappingURL=Base.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Base.js","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport Router from \"./Router\";\r\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, ArgsInfo } from \"./types\";\r\n\r\nclass SecurequServerBase extends Router {\r\n protected config: SecurequServerConfig;\r\n protected secret: string | null = null\r\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\r\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\r\n\r\n constructor(config: SecurequServerConfig) {\r\n super()\r\n if (!config.basepath) throw new Error(\"Basepath is required\");\r\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\r\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\r\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\r\n if (config.upload) {\r\n config.upload.maxFilesize = config.upload.maxFilesize || 50 * 1024 // 50MB default\r\n config.upload.checkFileType = config.upload.checkFileType || true\r\n }\r\n this.config = config\r\n for (let client of this.config.clients) {\r\n this.clients.set(client.origin, client.secret)\r\n }\r\n }\r\n\r\n protected async getSecret() {\r\n if (!this.secret) {\r\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\r\n }\r\n return this.secret\r\n }\r\n\r\n protected async clientInfo(path: string, origin: string) {\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n let splitUrl = path.split(\"?\")\r\n path = splitUrl[0]\r\n path = path.replace(this.config.basepath + \"/\", \"\")\r\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\r\n path = path.startsWith('/') ? path.substring(1) : path\r\n\r\n const split = path.split(\"/\")\r\n const hash = split.shift()\r\n if (!hash?.length || !this.clients.has(origin)) throw new Response(\"Client not allowed\", { status: 403 });\r\n let client = this.clients.get(origin as string) as string;\r\n let secret = client.substring(0, hash.length as number);\r\n let searchParams: { [key: string]: any } = {}\r\n if (splitUrl.length > 1) {\r\n if (isDev) {\r\n searchParams = Object.fromEntries(new URLSearchParams(decodeURIComponent(splitUrl[1])))\r\n } else {\r\n searchParams = await crypto.decrypt(decodeURIComponent(splitUrl[1]), secret) as any\r\n }\r\n }\r\n return {\r\n path: \"/\" + split.join('/'),\r\n secret,\r\n hash,\r\n searchParams\r\n }\r\n }\r\n\r\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\r\n const serverSecret = await this.getSecret()\r\n if (this.secret && signeture) {\r\n let info: any = await crypto.decrypt(signeture, serverSecret)\r\n let isHashValid = info.hash === hash\r\n let isNotExpired = info.expire > Date.now()\r\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\r\n }\r\n }\r\n\r\n async handleRequest(info: HandlerInfo, args?: ArgsInfo) {\r\n if (this.config.accept) {\r\n const is = await this.config.accept(info, args)\r\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\r\n }\r\n\r\n const { path, method } = info;\r\n let values: any = Object.values(this.routes[method]);\r\n for (let { test, handler } of values) {\r\n const match = test(path)\r\n if (match) {\r\n await handler({ ...info, params: match.params }, args)\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServerBase;"],"names":["SecurequServerBase","Router","constructor","config","super","this","secret","clients","Map","uploadMeta","basepath","Error","Object","keys","length","startsWith","endsWith","substring","upload","maxFilesize","checkFileType","client","set","origin","getSecret","crypto","hash","Math","random","toString","clientInfo","path","isDev","mode","splitUrl","split","replace","shift","has","Response","status","get","searchParams","fromEntries","URLSearchParams","decodeURIComponent","decrypt","join","isValidSigneture","signeture","serverSecret","info","isHashValid","isNotExpired","expire","Date","now","handleRequest","args","accept","method","values","routes","test","handler","match","assign","params","exports","default"],"mappings":"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"}
1
+ {"version":3,"file":"Base.js","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport Router from \"./Router\";\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\n\nclass SecurequServerBase extends Router {\n protected config: SecurequServerConfig;\n protected secret: string | null = null\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\n readonly CONTENT_TYPE = \"application/octet-stream\";\n\n constructor(config: SecurequServerConfig) {\n super()\n if (!config.basepath) throw new Error(\"Basepath is required\");\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\n if (config.upload) {\n config.upload.maxFilesize = config.upload.maxFilesize || 50 * 1024 // 50MB default\n config.upload.checkFileType = config.upload.checkFileType || true\n }\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\n this.config = config\n for (let client of this.config.clients) {\n this.clients.set(client.origin, client.secret)\n }\n }\n\n protected async getSecret() {\n if (!this.secret) {\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\n }\n return this.secret\n }\n\n protected async clientInfo(path: string, origin: string) {\n const isDev = path !== '/' && this.config.mode === 'development'\n let splitUrl = path.split(\"?\")\n path = splitUrl[0]\n path = path.replace(this.config.basepath + \"/\", \"\")\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\n path = path.startsWith('/') ? path.substring(1) : path\n\n const split = path.split(\"/\")\n const hash = split.shift()\n let client = this.clients.get(origin)\n if (!client) {\n client = this.clients.get(\"*\")\n }\n\n if (!hash?.length || !client) return null\n let secret = client.substring(0, hash.length as number);\n let searchParams: { [key: string]: any } = {}\n if (splitUrl.length > 1) {\n if (isDev) {\n searchParams = Object.fromEntries(new URLSearchParams(decodeURIComponent(splitUrl[1])))\n } else {\n searchParams = await crypto.decrypt(decodeURIComponent(splitUrl[1]), secret) as any\n }\n }\n return {\n path: \"/\" + split.join('/'),\n secret,\n hash,\n searchParams\n }\n }\n\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\n const serverSecret = await this.getSecret()\n if (this.secret && signeture) {\n let info: any = await crypto.decrypt(signeture, serverSecret)\n let isHashValid = info.hash === hash\n let isNotExpired = info.expire > Date.now()\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\n }\n }\n\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\n if (this.config.accept) {\n const is = await this.config.accept(info, metadata)\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\n }\n\n const { path, method } = info;\n let values: any = Object.values(this.routes[method]);\n for (let { test, handler } of values) {\n const match = test(path)\n if (match) {\n await handler({ ...info, params: match.params }, metadata)\n }\n }\n }\n\n}\n\nexport default SecurequServerBase;"],"names":["SecurequServerBase","Router","constructor","config","super","this","secret","clients","Map","uploadMeta","CONTENT_TYPE","basepath","Error","Object","keys","length","startsWith","endsWith","substring","upload","maxFilesize","checkFileType","mode","includes","client","set","origin","getSecret","crypto","hash","Math","random","toString","clientInfo","path","isDev","splitUrl","split","replace","shift","get","searchParams","fromEntries","URLSearchParams","decodeURIComponent","decrypt","join","isValidSigneture","signeture","serverSecret","info","isHashValid","isNotExpired","expire","Date","now","Response","status","handleRequest","metadata","accept","method","values","routes","test","handler","match","assign","params","exports","default"],"mappings":"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"}
package/server/Base.mjs CHANGED
@@ -1 +1 @@
1
- import t from"../include/crypto.mjs";import e from"./Router.mjs";class s extends e{constructor(t){if(super(),this.secret=null,this.clients=new Map,this.uploadMeta=new Map,!t.basepath)throw new Error("Basepath is required");if(!t.clients||0===Object.keys(t.clients).length)throw new Error("Atleast one client is required");t.basepath.startsWith("/")||(t.basepath=`/${t.basepath}`),t.basepath.endsWith("/")&&(t.basepath=t.basepath.substring(0,t.basepath.length-1)),t.upload&&(t.upload.maxFilesize=t.upload.maxFilesize||51200,t.upload.checkFileType=t.upload.checkFileType||!0),this.config=t;for(let t of this.config.clients)this.clients.set(t.origin,t.secret)}async getSecret(){return this.secret||(this.secret=await t.hash(Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15))),this.secret}async clientInfo(e,s){const i="/"!==e&&"development"===this.config.mode;let a=e.split("?");const n=(e=(e=(e=(e=a[0]).replace(this.config.basepath+"/","")).endsWith("/")?e.substring(0,e.length-1):e).startsWith("/")?e.substring(1):e).split("/"),r=n.shift();if(!(null==r?void 0:r.length)||!this.clients.has(s))throw new Response("Client not allowed",{status:403});let o=this.clients.get(s).substring(0,r.length),h={};return a.length>1&&(h=i?Object.fromEntries(new URLSearchParams(decodeURIComponent(a[1]))):await t.decrypt(decodeURIComponent(a[1]),o)),{path:"/"+n.join("/"),secret:o,hash:r,searchParams:h}}async isValidSigneture(e,s){const i=await this.getSecret();if(this.secret&&e){let a=await t.decrypt(e,i),n=a.hash===s,r=a.expire>Date.now();if(!n)throw new Response("Invalid Signeture",{status:403});if(!r)throw new Response("Signeture expired",{status:403})}}async handleRequest(t,e){if(this.config.accept){if(!await this.config.accept(t,e))throw new Response("Request not accepted",{status:403})}const{path:s,method:i}=t;let a=Object.values(this.routes[i]);for(let{test:i,handler:n}of a){const a=i(s);a&&await n(Object.assign(Object.assign({},t),{params:a.params}),e)}}}export{s as default};//# sourceMappingURL=Base.mjs.map
1
+ import t from"../include/crypto.mjs";import e from"./Router.mjs";class s extends e{constructor(t){if(super(),this.secret=null,this.clients=new Map,this.uploadMeta=new Map,this.CONTENT_TYPE="application/octet-stream",!t.basepath)throw new Error("Basepath is required");if(!t.clients||0===Object.keys(t.clients).length)throw new Error("Atleast one client is required");t.basepath.startsWith("/")||(t.basepath=`/${t.basepath}`),t.basepath.endsWith("/")&&(t.basepath=t.basepath.substring(0,t.basepath.length-1)),t.upload&&(t.upload.maxFilesize=t.upload.maxFilesize||51200,t.upload.checkFileType=t.upload.checkFileType||!0),t.mode=["production","development"].includes(t.mode||"")?t.mode:"production",this.config=t;for(let t of this.config.clients)this.clients.set(t.origin,t.secret)}async getSecret(){return this.secret||(this.secret=await t.hash(Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15))),this.secret}async clientInfo(e,s){const i="/"!==e&&"development"===this.config.mode;let a=e.split("?");const n=(e=(e=(e=(e=a[0]).replace(this.config.basepath+"/","")).endsWith("/")?e.substring(0,e.length-1):e).startsWith("/")?e.substring(1):e).split("/"),r=n.shift();let o=this.clients.get(s);if(o||(o=this.clients.get("*")),!(null==r?void 0:r.length)||!o)return null;let c=o.substring(0,r.length),h={};return a.length>1&&(h=i?Object.fromEntries(new URLSearchParams(decodeURIComponent(a[1]))):await t.decrypt(decodeURIComponent(a[1]),c)),{path:"/"+n.join("/"),secret:c,hash:r,searchParams:h}}async isValidSigneture(e,s){const i=await this.getSecret();if(this.secret&&e){let a=await t.decrypt(e,i),n=a.hash===s,r=a.expire>Date.now();if(!n)throw new Response("Invalid Signeture",{status:403});if(!r)throw new Response("Signeture expired",{status:403})}}async handleRequest(t,e){if(this.config.accept){if(!await this.config.accept(t,e))throw new Response("Request not accepted",{status:403})}const{path:s,method:i}=t;let a=Object.values(this.routes[i]);for(let{test:i,handler:n}of a){const a=i(s);a&&await n(Object.assign(Object.assign({},t),{params:a.params}),e)}}}export{s as default};//# sourceMappingURL=Base.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Base.mjs","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport Router from \"./Router\";\r\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, ArgsInfo } from \"./types\";\r\n\r\nclass SecurequServerBase extends Router {\r\n protected config: SecurequServerConfig;\r\n protected secret: string | null = null\r\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\r\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\r\n\r\n constructor(config: SecurequServerConfig) {\r\n super()\r\n if (!config.basepath) throw new Error(\"Basepath is required\");\r\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\r\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\r\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\r\n if (config.upload) {\r\n config.upload.maxFilesize = config.upload.maxFilesize || 50 * 1024 // 50MB default\r\n config.upload.checkFileType = config.upload.checkFileType || true\r\n }\r\n this.config = config\r\n for (let client of this.config.clients) {\r\n this.clients.set(client.origin, client.secret)\r\n }\r\n }\r\n\r\n protected async getSecret() {\r\n if (!this.secret) {\r\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\r\n }\r\n return this.secret\r\n }\r\n\r\n protected async clientInfo(path: string, origin: string) {\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n let splitUrl = path.split(\"?\")\r\n path = splitUrl[0]\r\n path = path.replace(this.config.basepath + \"/\", \"\")\r\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\r\n path = path.startsWith('/') ? path.substring(1) : path\r\n\r\n const split = path.split(\"/\")\r\n const hash = split.shift()\r\n if (!hash?.length || !this.clients.has(origin)) throw new Response(\"Client not allowed\", { status: 403 });\r\n let client = this.clients.get(origin as string) as string;\r\n let secret = client.substring(0, hash.length as number);\r\n let searchParams: { [key: string]: any } = {}\r\n if (splitUrl.length > 1) {\r\n if (isDev) {\r\n searchParams = Object.fromEntries(new URLSearchParams(decodeURIComponent(splitUrl[1])))\r\n } else {\r\n searchParams = await crypto.decrypt(decodeURIComponent(splitUrl[1]), secret) as any\r\n }\r\n }\r\n return {\r\n path: \"/\" + split.join('/'),\r\n secret,\r\n hash,\r\n searchParams\r\n }\r\n }\r\n\r\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\r\n const serverSecret = await this.getSecret()\r\n if (this.secret && signeture) {\r\n let info: any = await crypto.decrypt(signeture, serverSecret)\r\n let isHashValid = info.hash === hash\r\n let isNotExpired = info.expire > Date.now()\r\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\r\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\r\n }\r\n }\r\n\r\n async handleRequest(info: HandlerInfo, args?: ArgsInfo) {\r\n if (this.config.accept) {\r\n const is = await this.config.accept(info, args)\r\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\r\n }\r\n\r\n const { path, method } = info;\r\n let values: any = Object.values(this.routes[method]);\r\n for (let { test, handler } of values) {\r\n const match = test(path)\r\n if (match) {\r\n await handler({ ...info, params: match.params }, args)\r\n }\r\n }\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServerBase;"],"names":["SecurequServerBase","Router","constructor","config","super","this","secret","clients","Map","uploadMeta","basepath","Error","Object","keys","length","startsWith","endsWith","substring","upload","maxFilesize","checkFileType","client","set","origin","getSecret","crypto","hash","Math","random","toString","clientInfo","path","isDev","mode","splitUrl","split","replace","shift","has","Response","status","get","searchParams","fromEntries","URLSearchParams","decodeURIComponent","decrypt","join","isValidSigneture","signeture","serverSecret","info","isHashValid","isNotExpired","expire","Date","now","handleRequest","args","accept","method","values","routes","test","handler","match","assign","params"],"mappings":"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"}
1
+ {"version":3,"file":"Base.mjs","sources":["../../src/server/Base.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport Router from \"./Router\";\nimport { HandlerInfo, SecurequServerConfig, ServerClientSecret, ServerClientOrigin, UploadFileMeta, Metadata } from \"./types\";\n\nclass SecurequServerBase extends Router {\n protected config: SecurequServerConfig;\n protected secret: string | null = null\n protected clients = new Map<ServerClientOrigin, ServerClientSecret>();\n protected uploadMeta = new Map<string, UploadFileMeta & { expire: number }>();\n readonly CONTENT_TYPE = \"application/octet-stream\";\n\n constructor(config: SecurequServerConfig) {\n super()\n if (!config.basepath) throw new Error(\"Basepath is required\");\n if (!config.clients || Object.keys(config.clients).length === 0) throw new Error(\"Atleast one client is required\");\n if (!config.basepath.startsWith(\"/\")) config.basepath = `/${config.basepath}`;\n if (config.basepath.endsWith(\"/\")) config.basepath = config.basepath.substring(0, config.basepath.length - 1);\n if (config.upload) {\n config.upload.maxFilesize = config.upload.maxFilesize || 50 * 1024 // 50MB default\n config.upload.checkFileType = config.upload.checkFileType || true\n }\n config.mode = [\"production\", 'development'].includes(config.mode || \"\") ? config.mode : \"production\"\n this.config = config\n for (let client of this.config.clients) {\n this.clients.set(client.origin, client.secret)\n }\n }\n\n protected async getSecret() {\n if (!this.secret) {\n this.secret = await crypto.hash(Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15))\n }\n return this.secret\n }\n\n protected async clientInfo(path: string, origin: string) {\n const isDev = path !== '/' && this.config.mode === 'development'\n let splitUrl = path.split(\"?\")\n path = splitUrl[0]\n path = path.replace(this.config.basepath + \"/\", \"\")\n path = path.endsWith('/') ? path.substring(0, path.length - 1) : path\n path = path.startsWith('/') ? path.substring(1) : path\n\n const split = path.split(\"/\")\n const hash = split.shift()\n let client = this.clients.get(origin)\n if (!client) {\n client = this.clients.get(\"*\")\n }\n\n if (!hash?.length || !client) return null\n let secret = client.substring(0, hash.length as number);\n let searchParams: { [key: string]: any } = {}\n if (splitUrl.length > 1) {\n if (isDev) {\n searchParams = Object.fromEntries(new URLSearchParams(decodeURIComponent(splitUrl[1])))\n } else {\n searchParams = await crypto.decrypt(decodeURIComponent(splitUrl[1]), secret) as any\n }\n }\n return {\n path: \"/\" + split.join('/'),\n secret,\n hash,\n searchParams\n }\n }\n\n protected async isValidSigneture(signeture: string | undefined, hash: string) {\n const serverSecret = await this.getSecret()\n if (this.secret && signeture) {\n let info: any = await crypto.decrypt(signeture, serverSecret)\n let isHashValid = info.hash === hash\n let isNotExpired = info.expire > Date.now()\n if (!isHashValid) throw new Response(\"Invalid Signeture\", { status: 403 });\n if (!isNotExpired) throw new Response(\"Signeture expired\", { status: 403 });\n }\n }\n\n async handleRequest(info: HandlerInfo, metadata?: Metadata) {\n if (this.config.accept) {\n const is = await this.config.accept(info, metadata)\n if (!is) throw new Response(\"Request not accepted\", { status: 403 })\n }\n\n const { path, method } = info;\n let values: any = Object.values(this.routes[method]);\n for (let { test, handler } of values) {\n const match = test(path)\n if (match) {\n await handler({ ...info, params: match.params }, metadata)\n }\n }\n }\n\n}\n\nexport default SecurequServerBase;"],"names":["SecurequServerBase","Router","constructor","config","super","this","secret","clients","Map","uploadMeta","CONTENT_TYPE","basepath","Error","Object","keys","length","startsWith","endsWith","substring","upload","maxFilesize","checkFileType","mode","includes","client","set","origin","getSecret","crypto","hash","Math","random","toString","clientInfo","path","isDev","splitUrl","split","replace","shift","get","searchParams","fromEntries","URLSearchParams","decodeURIComponent","decrypt","join","isValidSigneture","signeture","serverSecret","info","isHashValid","isNotExpired","expire","Date","now","Response","status","handleRequest","metadata","accept","method","values","routes","test","handler","match","assign","params"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { HTTPMethods } from '../client/types.js';
2
2
  import { RouteFactory, HandlerFunction } from './types.js';
3
3
 
4
- declare class Router {
5
- protected routes: RouteFactory;
6
- addRoute(path: string, method: HTTPMethods, handler: HandlerFunction): Promise<void>;
7
- get(path: string, handler: HandlerFunction): Promise<void>;
8
- post(path: string, handler: HandlerFunction): Promise<void>;
9
- put(path: string, handler: HandlerFunction): Promise<void>;
10
- delete(path: string, handler: HandlerFunction): Promise<void>;
4
+ declare class Router {
5
+ protected routes: RouteFactory;
6
+ addRoute(path: string, method: HTTPMethods, handler: HandlerFunction): Promise<void>;
7
+ get(path: string, handler: HandlerFunction): Promise<void>;
8
+ post(path: string, handler: HandlerFunction): Promise<void>;
9
+ put(path: string, handler: HandlerFunction): Promise<void>;
10
+ delete(path: string, handler: HandlerFunction): Promise<void>;
11
11
  }
12
12
 
13
13
  export { Router as default };
@@ -1 +1 @@
1
- {"version":3,"file":"Router.js","sources":["../../src/server/Router.ts"],"sourcesContent":["import { HTTPMethods } from \"../client/types\";\r\nimport { HandlerFunction, RouteFactory } from \"./types\"\r\nimport { match } from \"path-to-regexp\";\r\n\r\nclass Router {\r\n protected routes: RouteFactory = {\r\n GET: {},\r\n POST: {},\r\n PUT: {},\r\n DELETE: {}\r\n };\r\n\r\n async addRoute(path: string, method: HTTPMethods, handler: HandlerFunction) {\r\n if (this.routes[method][path]) return\r\n this.routes[method][path] = {\r\n handler,\r\n test: match(path)\r\n }\r\n }\r\n\r\n async get(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'GET', handler)\r\n }\r\n\r\n async post(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'POST', handler)\r\n }\r\n\r\n async put(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'PUT', handler)\r\n }\r\n\r\n async delete(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'DELETE', handler)\r\n }\r\n}\r\n\r\nexport default Router;"],"names":["Object","defineProperty","exports","value","pathToRegexp","require","default","constructor","this","routes","GET","POST","PUT","DELETE","addRoute","path","method","handler","test","match","get","post","put"],"mappings":"AAIA,aAAAA,OAAAC,eAAAC,QAAA,aAAA,CAAAC,OAAA,IAAA,IAAAC,EAAAC,QAAA,kBA+BCH,QAAAI,QA/BD,MAAA,WAAAC,GACaC,KAAAC,OAAuB,CAC9BC,IAAK,CAAA,EACLC,KAAM,CAAA,EACNC,IAAK,CAAA,EACLC,OAAQ,CAAA,EA0Bd,CAvBG,cAAMC,CAASC,EAAcC,EAAqBC,GAC3CT,KAAKC,OAAOO,GAAQD,KACxBP,KAAKC,OAAOO,GAAQD,GAAQ,CACzBE,UACAC,KAAMC,EAAAA,MAAMJ,IAElB,CAEA,SAAMK,CAAIL,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,UAAMI,CAAKN,EAAcE,GACtBT,KAAKM,SAASC,EAAM,OAAQE,EAC/B,CAEA,SAAMK,CAAIP,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,YAAM,CAAOF,EAAcE,GACxBT,KAAKM,SAASC,EAAM,SAAUE,EACjC"}
1
+ {"version":3,"file":"Router.js","sources":["../../src/server/Router.ts"],"sourcesContent":["import { HTTPMethods } from \"../client/types\";\nimport { HandlerFunction, RouteFactory } from \"./types\"\nimport { match } from \"path-to-regexp\";\n\nclass Router {\n protected routes: RouteFactory = {\n GET: {},\n POST: {},\n PUT: {},\n DELETE: {}\n };\n\n async addRoute(path: string, method: HTTPMethods, handler: HandlerFunction) {\n if (this.routes[method][path]) return\n this.routes[method][path] = {\n handler,\n test: match(path)\n }\n }\n\n async get(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'GET', handler)\n }\n\n async post(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'POST', handler)\n }\n\n async put(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'PUT', handler)\n }\n\n async delete(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'DELETE', handler)\n }\n}\n\nexport default Router;"],"names":["Object","defineProperty","exports","value","pathToRegexp","require","default","constructor","this","routes","GET","POST","PUT","DELETE","addRoute","path","method","handler","test","match","get","post","put"],"mappings":"AAIA,aAAAA,OAAAC,eAAAC,QAAA,aAAA,CAAAC,OAAA,IAAA,IAAAC,EAAAC,QAAA,kBA+BCH,QAAAI,QA/BD,MAAA,WAAAC,GACaC,KAAAC,OAAuB,CAC9BC,IAAK,CAAA,EACLC,KAAM,CAAA,EACNC,IAAK,CAAA,EACLC,OAAQ,CAAA,EA0Bd,CAvBG,cAAMC,CAASC,EAAcC,EAAqBC,GAC3CT,KAAKC,OAAOO,GAAQD,KACxBP,KAAKC,OAAOO,GAAQD,GAAQ,CACzBE,UACAC,KAAMC,EAAAA,MAAMJ,IAElB,CAEA,SAAMK,CAAIL,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,UAAMI,CAAKN,EAAcE,GACtBT,KAAKM,SAASC,EAAM,OAAQE,EAC/B,CAEA,SAAMK,CAAIP,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,YAAM,CAAOF,EAAcE,GACxBT,KAAKM,SAASC,EAAM,SAAUE,EACjC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Router.mjs","sources":["../../src/server/Router.ts"],"sourcesContent":["import { HTTPMethods } from \"../client/types\";\r\nimport { HandlerFunction, RouteFactory } from \"./types\"\r\nimport { match } from \"path-to-regexp\";\r\n\r\nclass Router {\r\n protected routes: RouteFactory = {\r\n GET: {},\r\n POST: {},\r\n PUT: {},\r\n DELETE: {}\r\n };\r\n\r\n async addRoute(path: string, method: HTTPMethods, handler: HandlerFunction) {\r\n if (this.routes[method][path]) return\r\n this.routes[method][path] = {\r\n handler,\r\n test: match(path)\r\n }\r\n }\r\n\r\n async get(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'GET', handler)\r\n }\r\n\r\n async post(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'POST', handler)\r\n }\r\n\r\n async put(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'PUT', handler)\r\n }\r\n\r\n async delete(path: string, handler: HandlerFunction) {\r\n this.addRoute(path, 'DELETE', handler)\r\n }\r\n}\r\n\r\nexport default Router;"],"names":["match","Router","constructor","this","routes","GET","POST","PUT","DELETE","addRoute","path","method","handler","test","get","post","put"],"mappings":"gBAIAA,MAAA,iBAAA,MAAMC,EAAN,WAAAC,GACaC,KAAAC,OAAuB,CAC9BC,IAAK,CAAA,EACLC,KAAM,CAAA,EACNC,IAAK,CAAA,EACLC,OAAQ,CAAA,EA0Bd,CAvBG,cAAMC,CAASC,EAAcC,EAAqBC,GAC3CT,KAAKC,OAAOO,GAAQD,KACxBP,KAAKC,OAAOO,GAAQD,GAAQ,CACzBE,UACAC,KAAMb,EAAMU,IAElB,CAEA,SAAMI,CAAIJ,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,UAAMG,CAAKL,EAAcE,GACtBT,KAAKM,SAASC,EAAM,OAAQE,EAC/B,CAEA,SAAMI,CAAIN,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,YAAM,CAAOF,EAAcE,GACxBT,KAAKM,SAASC,EAAM,SAAUE,EACjC,SACFX"}
1
+ {"version":3,"file":"Router.mjs","sources":["../../src/server/Router.ts"],"sourcesContent":["import { HTTPMethods } from \"../client/types\";\nimport { HandlerFunction, RouteFactory } from \"./types\"\nimport { match } from \"path-to-regexp\";\n\nclass Router {\n protected routes: RouteFactory = {\n GET: {},\n POST: {},\n PUT: {},\n DELETE: {}\n };\n\n async addRoute(path: string, method: HTTPMethods, handler: HandlerFunction) {\n if (this.routes[method][path]) return\n this.routes[method][path] = {\n handler,\n test: match(path)\n }\n }\n\n async get(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'GET', handler)\n }\n\n async post(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'POST', handler)\n }\n\n async put(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'PUT', handler)\n }\n\n async delete(path: string, handler: HandlerFunction) {\n this.addRoute(path, 'DELETE', handler)\n }\n}\n\nexport default Router;"],"names":["match","Router","constructor","this","routes","GET","POST","PUT","DELETE","addRoute","path","method","handler","test","get","post","put"],"mappings":"gBAIAA,MAAA,iBAAA,MAAMC,EAAN,WAAAC,GACaC,KAAAC,OAAuB,CAC9BC,IAAK,CAAA,EACLC,KAAM,CAAA,EACNC,IAAK,CAAA,EACLC,OAAQ,CAAA,EA0Bd,CAvBG,cAAMC,CAASC,EAAcC,EAAqBC,GAC3CT,KAAKC,OAAOO,GAAQD,KACxBP,KAAKC,OAAOO,GAAQD,GAAQ,CACzBE,UACAC,KAAMb,EAAMU,IAElB,CAEA,SAAMI,CAAIJ,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,UAAMG,CAAKL,EAAcE,GACtBT,KAAKM,SAASC,EAAM,OAAQE,EAC/B,CAEA,SAAMI,CAAIN,EAAcE,GACrBT,KAAKM,SAASC,EAAM,MAAOE,EAC9B,CAEA,YAAM,CAAOF,EAAcE,GACxBT,KAAKM,SAASC,EAAM,SAAUE,EACjC,SACFX"}
package/server/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { ArgsInfo, ListenerInfo, ServerResponse } from './types.js';
1
+ import { Metadata, ListenerInfo, ServerResponse } from './types.js';
2
2
  import SecurequServerBase from './Base.js';
3
3
 
4
- declare class SecurequServer extends SecurequServerBase {
5
- handshake(body: any, clientInfo: any): Promise<void>;
6
- upload(body: any, clientInfo: any, signeture: string, args?: ArgsInfo): Promise<void>;
7
- listen({ path, body, method, origin, signeture }: ListenerInfo, args?: ArgsInfo): Promise<ServerResponse>;
4
+ declare class SecurequServer extends SecurequServerBase {
5
+ handshake(body: any, clientInfo: any): Promise<void>;
6
+ upload(body: any, clientInfo: any, signeture: string, metadata?: Metadata): Promise<void>;
7
+ listen(url: string, { body, headers, metadata }: ListenerInfo): Promise<ServerResponse>;
8
8
  }
9
9
 
10
10
  export { SecurequServer as default };
package/server/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../include/crypto.js"),t=require("./Base.js"),i=require("../include/FileScaner.js");class a extends t.default{async handshake(t,i){var a,s;const n=await e.default.decryptBuffer(t,i.secret),o=await this.getSecret();if(!n)throw new Error("Invalid handshake data");if(n.hash!==i.hash)throw new Error("Invalid handshake");if(n.secret!==i.secret)throw new Error("Invalid handshake secret");if(Date.now()-n.clientTime>3e4)throw new Error("Handshake expired");const l=new Date;throw{timeDiffarenc:new Date(n.clientTime).getTime()-l.getTime(),maxFileSize:(null===(a=this.config.upload)||void 0===a?void 0:a.maxFilesize)||null,dev:"development"===this.config.mode,checkFileType:(null===(s=this.config.upload)||void 0===s?void 0:s.checkFileType)||!1,signeture:await e.default.encrypt({expire:Date.now()+3e4,hash:i.hash},o)}}async upload(t,a,s,n){var o;const l=await e.default.decryptBuffer(t,a.secret),r=await e.default.decrypt(s,a.secret);await this.isValidSigneture(r.signeture,a.hash);const d=this.config.upload;if(!(null==d?void 0:d.chunk)||!(null==d?void 0:d.complete))throw new Response("Upload not supported",{status:403});if("failed"===(null==l?void 0:l.type)){const e=this.uploadMeta.get(l.fileid);throw e&&d.failed?(await d.failed(e,n),this.uploadMeta.delete(l.fileid),{success:!0}):new Response("Invalid upload",{status:400})}if("meta"===l.type){if((null==d?void 0:d.maxFilesize)&&l.filesize>1024*d.maxFilesize)throw new Response(`File size exceeds the limit of ${d.maxFilesize} KB`,{status:413});throw this.uploadMeta.set(l.fileid,Object.assign(Object.assign({},l),{expire:Date.now()+36e5})),this.uploadMeta.forEach((e,t)=>{e.expire<Date.now()&&this.uploadMeta.delete(t)}),l}{const{chunk:e,fileId:t,chunkIndex:a}=l,s=this.uploadMeta.get(t);if(!s)throw new Response("Invalid upload meta",{status:400});if(d.checkFileType&&0===a){if(!i.fileScaner(e))throw new Error("Unknown or unsupported file type")}if((null===(o=this.config.upload)||void 0===o?void 0:o.maxFilesize)&&l.filesize>1024*this.config.upload.maxFilesize)throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize/1024} MB`,{status:413});if(await d.chunk(e,{filename:s.filename,filesize:s.filesize,filetype:s.filetype,fileid:s.fileid,totalChunks:s.totalChunks,chunkIndex:a},n),a+1===s.totalChunks){const e=await d.complete(s,n);throw this.uploadMeta.delete(t),e}throw l}}async listen({path:t,body:i,method:a,origin:s,signeture:n},o){let l=await this.clientInfo(t,s);const r="/"!==(t=l.path)&&"development"===this.config.mode;try{if("/"===t){if(!["POST","PUT"].includes(a))throw new Response("Invalid method",{status:405});"POST"===a?await this.handshake(i,l):await this.upload(i,l,n,o)}const s=await e.default.decrypt(n,l.secret);if(await this.isValidSigneture(s.signeture,l.hash),s.expire<Date.now())throw new Response("Request expired",{status:403});let d=null;if(i)if(r){const e=(new TextDecoder).decode(i);d=JSON.parse(e)}else d=await e.default.decryptBuffer(i,l.secret);await this.handleRequest({method:a,path:t,body:d,searchParams:l.searchParams,params:{}},o)}catch(t){const i=t instanceof Error,a=t instanceof Response;let s=i?t.message:a?await t.text():t;return r?{status:i?404:(null==t?void 0:t.status)||200,content:JSON.stringify(s)}:{status:i?404:(null==t?void 0:t.status)||200,content:await e.default.encryptBuffer(s,l.secret)}}return r?{status:404,content:"Not found"}:{status:404,content:await e.default.encryptBuffer("Not found",l.secret)}}}exports.default=a;//# sourceMappingURL=index.js.map
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../include/crypto.js"),t=require("./Base.js"),i=require("../include/FileScaner.js");class a extends t.default{async handshake(t,i){var a,s;const n=await e.default.decryptBuffer(t,i.secret),o=await this.getSecret();if(!n)throw new Error("Invalid handshake data");if(n.hash!==i.hash)throw new Error("Invalid handshake");if(n.secret!==i.secret)throw new Error("Invalid handshake secret");if(Date.now()-n.clientTime>3e4)throw new Error("Handshake expired");const l=new Date;throw{timeDiffarenc:new Date(n.clientTime).getTime()-l.getTime(),maxFileSize:(null===(a=this.config.upload)||void 0===a?void 0:a.maxFilesize)||null,dev:"development"===this.config.mode,checkFileType:(null===(s=this.config.upload)||void 0===s?void 0:s.checkFileType)||!1,signeture:await e.default.encrypt({expire:Date.now()+3e4,hash:i.hash},o)}}async upload(t,a,s,n){var o;const l=await e.default.decryptBuffer(t,a.secret),r=await e.default.decrypt(s,a.secret);await this.isValidSigneture(r.signeture,a.hash);const d=this.config.upload;if(!(null==d?void 0:d.chunk)||!(null==d?void 0:d.complete))throw new Response("Upload not supported",{status:403});if("failed"===(null==l?void 0:l.type)){const e=this.uploadMeta.get(l.fileid);throw e&&d.failed?(await d.failed(e,n),this.uploadMeta.delete(l.fileid),{success:!0}):new Response("Invalid upload",{status:400})}if("meta"===l.type){if((null==d?void 0:d.maxFilesize)&&l.filesize>1024*d.maxFilesize)throw new Response(`File size exceeds the limit of ${d.maxFilesize} KB`,{status:413});throw this.uploadMeta.set(l.fileid,Object.assign(Object.assign({},l),{expire:Date.now()+36e5})),this.uploadMeta.forEach((e,t)=>{e.expire<Date.now()&&this.uploadMeta.delete(t)}),l}{const{chunk:e,fileId:t,chunkIndex:a}=l,s=this.uploadMeta.get(t);if(!s)throw new Response("Invalid upload meta",{status:400});if(d.checkFileType&&0===a){if(!i.fileScaner(e))throw new Error("Unknown or unsupported file type")}if((null===(o=this.config.upload)||void 0===o?void 0:o.maxFilesize)&&l.filesize>1024*this.config.upload.maxFilesize)throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize/1024} MB`,{status:413});if(await d.chunk(e,{filename:s.filename,filesize:s.filesize,filetype:s.filetype,fileid:s.fileid,totalChunks:s.totalChunks,chunkIndex:a},n),a+1===s.totalChunks){const e=await d.complete(s,n);throw this.uploadMeta.delete(t),e}throw l}}async listen(t,{body:i,headers:a,metadata:s}){const n=a["x-signeture"]||"",o=a["x-origin"]||"",l=a["x-method"]||"POST";let r=await this.clientInfo(t,o);if(!r)return{status:403,content:"Client not allowed"};let d=r.path;const u="/"!==d&&"development"===this.config.mode;try{if("/"===d){if(!["POST","PUT"].includes(l))throw new Response("Invalid method",{status:405});"POST"===l?await this.handshake(i,r):await this.upload(i,r,n,s)}const t=await e.default.decrypt(n,r.secret);if(await this.isValidSigneture(t.signeture,r.hash),t.expire<Date.now())throw new Response("Request expired",{status:403});let a=null;if(i)if(u){const e=(new TextDecoder).decode(i);a=JSON.parse(e)}else a=await e.default.decryptBuffer(i,r.secret);await this.handleRequest({method:l,path:d,body:a,searchParams:r.searchParams,params:{}},s)}catch(t){const i=t instanceof Error,a=t instanceof Response;let s=i?t.message:a?await t.text():t;return u?{status:i?404:(null==t?void 0:t.status)||200,content:JSON.stringify(s)}:{status:i?404:(null==t?void 0:t.status)||200,content:await e.default.encryptBuffer(s,r.secret)}}return u?{status:404,content:"Not found"}:{status:404,content:await e.default.encryptBuffer("Not found",r.secret)}}}exports.default=a;//# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/server/index.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport { ArgsInfo, ListenerInfo, ServerResponse } from \"./types\";\r\nimport SecurequServerBase from \"./Base\";\r\nimport fileScaner from \"../include/FileScaner\";\r\n\r\nclass SecurequServer extends SecurequServerBase {\r\n\r\n async handshake(body: any, clientInfo: any) {\r\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\r\n const serverSecret = await this.getSecret()\r\n if (!data) throw new Error(\"Invalid handshake data\");\r\n if (data.hash !== clientInfo.hash) {\r\n throw new Error(\"Invalid handshake\");\r\n } else if (data.secret !== clientInfo.secret) {\r\n throw new Error(\"Invalid handshake secret\");\r\n } else if (Date.now() - data.clientTime > 30000) { // 30 seconds\r\n throw new Error(\"Handshake expired\");\r\n }\r\n\r\n const serverTime = new Date();\r\n const clientDate = new Date(data.clientTime);\r\n const offsetMs = clientDate.getTime() - serverTime.getTime();\r\n\r\n let info = {\r\n timeDiffarenc: offsetMs,\r\n maxFileSize: this.config.upload?.maxFilesize || null,\r\n dev: this.config.mode === 'development',\r\n checkFileType: this.config.upload?.checkFileType || false,\r\n signeture: await crypto.encrypt({\r\n expire: Date.now() + 30000, // 30 seconds\r\n hash: clientInfo.hash\r\n }, serverSecret)\r\n }\r\n throw info\r\n }\r\n\r\n async upload(body: any, clientInfo: any, signeture: string, args?: ArgsInfo) {\r\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\r\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\r\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\r\n const upload = this.config.upload\r\n\r\n if (!upload?.chunk || !upload?.complete) {\r\n throw new Response(\"Upload not supported\", { status: 403 })\r\n }\r\n\r\n if (data?.type === 'failed') {\r\n const meta = this.uploadMeta.get(data.fileid)\r\n if (meta && upload.failed) {\r\n await upload.failed(meta, args)\r\n this.uploadMeta.delete(data.fileid)\r\n throw { success: true }\r\n } else {\r\n throw new Response(\"Invalid upload\", { status: 400 })\r\n }\r\n } else if (data.type === 'meta') {\r\n if (upload?.maxFilesize && data.filesize > upload.maxFilesize * 1024) {\r\n throw new Response(`File size exceeds the limit of ${upload.maxFilesize} KB`, { status: 413 })\r\n }\r\n this.uploadMeta.set(data.fileid, {\r\n ...data,\r\n expire: Date.now() + 3600000 // 1 hour\r\n })\r\n this.uploadMeta.forEach((meta, key) => {\r\n if (meta.expire < Date.now()) {\r\n this.uploadMeta.delete(key)\r\n }\r\n })\r\n\r\n throw data\r\n } else {\r\n const { chunk, fileId, chunkIndex } = data;\r\n const meta = this.uploadMeta.get(fileId)\r\n if (!meta) {\r\n throw new Response(\"Invalid upload meta\", { status: 400 })\r\n }\r\n if (upload.checkFileType && chunkIndex === 0) {\r\n let fileType = fileScaner(chunk);\r\n if (!fileType) {\r\n throw new Error(\"Unknown or unsupported file type\");\r\n }\r\n }\r\n\r\n if (this.config.upload?.maxFilesize && data.filesize > this.config.upload.maxFilesize * 1024) {\r\n throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize / 1024} MB`, { status: 413 })\r\n }\r\n await upload.chunk(chunk, {\r\n filename: meta.filename,\r\n filesize: meta.filesize,\r\n filetype: meta.filetype,\r\n fileid: meta.fileid,\r\n totalChunks: meta.totalChunks,\r\n chunkIndex,\r\n }, args)\r\n if (chunkIndex + 1 === meta.totalChunks) {\r\n const filepath = await upload.complete(meta, args)\r\n this.uploadMeta.delete(fileId)\r\n throw filepath\r\n }\r\n throw data\r\n }\r\n }\r\n\r\n async listen({ path, body, method, origin, signeture }: ListenerInfo, args?: ArgsInfo): Promise<ServerResponse> {\r\n let clientInfo = await this.clientInfo(path, origin)\r\n path = clientInfo.path\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n try {\r\n if (path === '/') {\r\n if (!['POST', 'PUT'].includes(method)) throw new Response(\"Invalid method\", { status: 405 });\r\n method === \"POST\"\r\n ? await this.handshake(body, clientInfo)\r\n : await this.upload(body, clientInfo, signeture, args);\r\n }\r\n\r\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\r\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\r\n\r\n // if reques is expired\r\n if (decryptSigneture.expire < Date.now()) throw new Response(\"Request expired\", { status: 403 });\r\n let data: any = null\r\n if (body) {\r\n if (isDev) {\r\n const decoder = new TextDecoder();\r\n const text = decoder.decode(body);\r\n data = JSON.parse(text)\r\n } else {\r\n data = await crypto.decryptBuffer(body, clientInfo.secret)\r\n }\r\n }\r\n\r\n await this.handleRequest({\r\n method,\r\n path,\r\n body: data,\r\n searchParams: clientInfo.searchParams,\r\n params: {}\r\n }, args);\r\n } catch (info: any) {\r\n const isError = info instanceof Error\r\n const isResponse = info instanceof Response\r\n let content = isError ? info.message : (isResponse ? await info.text() : info);\r\n if (path === '/') {\r\n\r\n }\r\n if (isDev) {\r\n return {\r\n status: isError ? 404 : (info?.status || 200),\r\n content: JSON.stringify(content)\r\n };\r\n }\r\n return {\r\n status: isError ? 404 : (info?.status || 200),\r\n content: await crypto.encryptBuffer(content, clientInfo.secret)\r\n };\r\n }\r\n\r\n if (isDev) {\r\n return {\r\n status: 404,\r\n content: \"Not found\"\r\n };\r\n }\r\n\r\n return {\r\n status: 404,\r\n content: await crypto.encryptBuffer(\"Not found\", clientInfo.secret)\r\n };\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServer;"],"names":["SecurequServer","SecurequServerBase","handshake","body","clientInfo","data","crypto","decryptBuffer","secret","serverSecret","this","getSecret","Error","hash","Date","now","clientTime","serverTime","timeDiffarenc","getTime","maxFileSize","_a","config","upload","maxFilesize","dev","mode","checkFileType","_b","signeture","encrypt","expire","args","decryptSigneture","decrypt","isValidSigneture","chunk","complete","Response","status","type","meta","uploadMeta","get","fileid","failed","delete","success","filesize","set","Object","assign","forEach","key","fileId","chunkIndex","fileScaner","filename","filetype","totalChunks","filepath","listen","path","method","origin","isDev","includes","text","TextDecoder","decode","JSON","parse","handleRequest","searchParams","params","info","isError","isResponse","content","message","stringify","encryptBuffer","exports","default"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/server/index.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport { Metadata, ListenerInfo, ServerResponse } from \"./types\";\nimport SecurequServerBase from \"./Base\";\nimport fileScaner from \"../include/FileScaner\";\nimport { HTTPMethods } from \"../client/types\";\n\nclass SecurequServer extends SecurequServerBase {\n\n async handshake(body: any, clientInfo: any) {\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\n const serverSecret = await this.getSecret()\n if (!data) throw new Error(\"Invalid handshake data\");\n if (data.hash !== clientInfo.hash) {\n throw new Error(\"Invalid handshake\");\n } else if (data.secret !== clientInfo.secret) {\n throw new Error(\"Invalid handshake secret\");\n } else if (Date.now() - data.clientTime > 30000) { // 30 seconds\n throw new Error(\"Handshake expired\");\n }\n\n const serverTime = new Date();\n const clientDate = new Date(data.clientTime);\n const offsetMs = clientDate.getTime() - serverTime.getTime();\n\n let info = {\n timeDiffarenc: offsetMs,\n maxFileSize: this.config.upload?.maxFilesize || null,\n dev: this.config.mode === 'development',\n checkFileType: this.config.upload?.checkFileType || false,\n signeture: await crypto.encrypt({\n expire: Date.now() + 30000, // 30 seconds\n hash: clientInfo.hash\n }, serverSecret)\n }\n throw info\n }\n\n async upload(body: any, clientInfo: any, signeture: string, metadata?: Metadata) {\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\n const upload = this.config.upload\n\n if (!upload?.chunk || !upload?.complete) {\n throw new Response(\"Upload not supported\", { status: 403 })\n }\n\n if (data?.type === 'failed') {\n const meta = this.uploadMeta.get(data.fileid)\n if (meta && upload.failed) {\n await upload.failed(meta, metadata)\n this.uploadMeta.delete(data.fileid)\n throw { success: true }\n } else {\n throw new Response(\"Invalid upload\", { status: 400 })\n }\n } else if (data.type === 'meta') {\n if (upload?.maxFilesize && data.filesize > upload.maxFilesize * 1024) {\n throw new Response(`File size exceeds the limit of ${upload.maxFilesize} KB`, { status: 413 })\n }\n this.uploadMeta.set(data.fileid, {\n ...data,\n expire: Date.now() + 3600000 // 1 hour\n })\n this.uploadMeta.forEach((meta, key) => {\n if (meta.expire < Date.now()) {\n this.uploadMeta.delete(key)\n }\n })\n\n throw data\n } else {\n const { chunk, fileId, chunkIndex } = data;\n const meta = this.uploadMeta.get(fileId)\n if (!meta) {\n throw new Response(\"Invalid upload meta\", { status: 400 })\n }\n if (upload.checkFileType && chunkIndex === 0) {\n let fileType = fileScaner(chunk);\n if (!fileType) {\n throw new Error(\"Unknown or unsupported file type\");\n }\n }\n\n if (this.config.upload?.maxFilesize && data.filesize > this.config.upload.maxFilesize * 1024) {\n throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize / 1024} MB`, { status: 413 })\n }\n await upload.chunk(chunk, {\n filename: meta.filename,\n filesize: meta.filesize,\n filetype: meta.filetype,\n fileid: meta.fileid,\n totalChunks: meta.totalChunks,\n chunkIndex,\n }, metadata)\n if (chunkIndex + 1 === meta.totalChunks) {\n const filepath = await upload.complete(meta, metadata)\n this.uploadMeta.delete(fileId)\n throw filepath\n }\n throw data\n }\n }\n\n async listen(url: string, { body, headers, metadata }: ListenerInfo): Promise<ServerResponse> {\n\n const signeture = headers['x-signeture'] || '';\n const origin = headers['x-origin'] || '';\n const method: HTTPMethods = headers['x-method'] || 'POST' as any\n\n let clientInfo = await this.clientInfo(url, origin)\n if (!clientInfo) {\n return {\n status: 403,\n content: \"Client not allowed\"\n }\n }\n let path = clientInfo.path\n const isDev = path !== '/' && this.config.mode === 'development'\n try {\n if (path === '/') {\n if (!['POST', 'PUT'].includes(method)) throw new Response(\"Invalid method\", { status: 405 });\n method === \"POST\"\n ? await this.handshake(body, clientInfo)\n : await this.upload(body, clientInfo, signeture, metadata);\n }\n\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\n\n // if reques is expired\n if (decryptSigneture.expire < Date.now()) throw new Response(\"Request expired\", { status: 403 });\n let data: any = null\n if (body) {\n if (isDev) {\n const decoder = new TextDecoder();\n const text = decoder.decode(body);\n data = JSON.parse(text)\n } else {\n data = await crypto.decryptBuffer(body, clientInfo.secret)\n }\n }\n\n await this.handleRequest({\n method,\n path,\n body: data,\n searchParams: clientInfo.searchParams,\n params: {}\n }, metadata);\n } catch (info: any) {\n const isError = info instanceof Error\n const isResponse = info instanceof Response\n let content = isError ? info.message : (isResponse ? await info.text() : info);\n if (isDev) {\n return {\n status: isError ? 404 : (info?.status || 200),\n content: JSON.stringify(content)\n };\n }\n return {\n status: isError ? 404 : (info?.status || 200),\n content: await crypto.encryptBuffer(content, clientInfo.secret)\n };\n }\n\n if (isDev) {\n return {\n status: 404,\n content: \"Not found\"\n };\n }\n\n return {\n status: 404,\n content: await crypto.encryptBuffer(\"Not found\", clientInfo.secret)\n };\n }\n\n}\n\nexport default SecurequServer;"],"names":["SecurequServer","SecurequServerBase","handshake","body","clientInfo","data","crypto","decryptBuffer","secret","serverSecret","this","getSecret","Error","hash","Date","now","clientTime","serverTime","timeDiffarenc","getTime","maxFileSize","_a","config","upload","maxFilesize","dev","mode","checkFileType","_b","signeture","encrypt","expire","metadata","decryptSigneture","decrypt","isValidSigneture","chunk","complete","Response","status","type","meta","uploadMeta","get","fileid","failed","delete","success","filesize","set","Object","assign","forEach","key","fileId","chunkIndex","fileScaner","filename","filetype","totalChunks","filepath","listen","url","headers","origin","method","content","path","isDev","includes","text","TextDecoder","decode","JSON","parse","handleRequest","searchParams","params","info","isError","isResponse","message","stringify","encryptBuffer","exports","default"],"mappings":"uKAMA,MAAMA,UAAuBC,EAAAA,QAE1B,eAAMC,CAAUC,EAAWC,WACxB,MAAMC,QAAkBC,EAAAA,QAAOC,cAAcJ,EAAMC,EAAWI,QACxDC,QAAqBC,KAAKC,YAChC,IAAKN,EAAM,MAAM,IAAIO,MAAM,0BAC3B,GAAIP,EAAKQ,OAAST,EAAWS,KAC1B,MAAM,IAAID,MAAM,qBACZ,GAAIP,EAAKG,SAAWJ,EAAWI,OACnC,MAAM,IAAII,MAAM,4BACZ,GAAIE,KAAKC,MAAQV,EAAKW,WAAa,IACvC,MAAM,IAAIJ,MAAM,qBAGnB,MAAMK,EAAa,IAAIH,KAcvB,KAVW,CACRI,cAJgB,IAAIJ,KAAKT,EAAKW,YACLG,UAAYF,EAAWE,UAIhDC,aAA+B,QAAlBC,EAAAX,KAAKY,OAAOC,cAAM,IAAAF,OAAA,EAAAA,EAAEG,cAAe,KAChDC,IAA0B,gBAArBf,KAAKY,OAAOI,KACjBC,eAAiC,QAAlBC,EAAAlB,KAAKY,OAAOC,cAAM,IAAAK,OAAA,EAAAA,EAAED,iBAAiB,EACpDE,gBAAiBvB,EAAAA,QAAOwB,QAAQ,CAC7BC,OAAQjB,KAAKC,MAAQ,IACrBF,KAAMT,EAAWS,MACjBJ,GAGT,CAEA,YAAMc,CAAOpB,EAAWC,EAAiByB,EAAmBG,SACzD,MAAM3B,QAAkBC,EAAAA,QAAOC,cAAcJ,EAAMC,EAAWI,QACxDyB,QAAyB3B,EAAAA,QAAO4B,QAAQL,EAAWzB,EAAWI,cAC9DE,KAAKyB,iBAAiBF,EAAiBJ,UAAWzB,EAAWS,MACnE,MAAMU,EAASb,KAAKY,OAAOC,OAE3B,KAAKA,aAAM,EAANA,EAAQa,UAAUb,eAAAA,EAAQc,UAC5B,MAAM,IAAIC,SAAS,uBAAwB,CAAEC,OAAQ,MAGxD,GAAmB,YAAflC,aAAI,EAAJA,EAAMmC,MAAmB,CAC1B,MAAMC,EAAO/B,KAAKgC,WAAWC,IAAItC,EAAKuC,QACtC,MAAIH,GAAQlB,EAAOsB,cACVtB,EAAOsB,OAAOJ,EAAMT,GAC1BtB,KAAKgC,WAAWI,OAAOzC,EAAKuC,QACtB,CAAEG,SAAS,IAEX,IAAIT,SAAS,iBAAkB,CAAEC,OAAQ,KAEpD,CAAM,GAAkB,SAAdlC,EAAKmC,KAAiB,CAC9B,IAAIjB,aAAM,EAANA,EAAQC,cAAenB,EAAK2C,SAAgC,KAArBzB,EAAOC,YAC/C,MAAM,IAAIc,SAAS,kCAAkCf,EAAOC,iBAAkB,CAAEe,OAAQ,MAY3F,MAVA7B,KAAKgC,WAAWO,IAAI5C,EAAKuC,OAAMM,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EACzB9C,IACH0B,OAAQjB,KAAKC,MAAQ,QAExBL,KAAKgC,WAAWU,QAAQ,CAACX,EAAMY,KACxBZ,EAAKV,OAASjB,KAAKC,OACpBL,KAAKgC,WAAWI,OAAOO,KAIvBhD,CACR,CAAM,CACJ,MAAM+B,MAAEA,EAAKkB,OAAEA,EAAMC,WAAEA,GAAelD,EAChCoC,EAAO/B,KAAKgC,WAAWC,IAAIW,GACjC,IAAKb,EACF,MAAM,IAAIH,SAAS,sBAAuB,CAAEC,OAAQ,MAEvD,GAAIhB,EAAOI,eAAgC,IAAf4B,EAAkB,CAE3C,IADeC,EAAAA,WAAWpB,GAEvB,MAAM,IAAIxB,MAAM,mCAErB,CAED,IAAsB,UAAlBF,KAAKY,OAAOC,cAAM,IAAAF,OAAA,EAAAA,EAAEG,cAAenB,EAAK2C,SAA4C,KAAjCtC,KAAKY,OAAOC,OAAOC,YACvE,MAAM,IAAIc,SAAS,kCAAkC5B,KAAKY,OAAOC,OAAOC,YAAc,UAAW,CAAEe,OAAQ,MAU9G,SARMhB,EAAOa,MAAMA,EAAO,CACvBqB,SAAUhB,EAAKgB,SACfT,SAAUP,EAAKO,SACfU,SAAUjB,EAAKiB,SACfd,OAAQH,EAAKG,OACbe,YAAalB,EAAKkB,YAClBJ,cACAvB,GACCuB,EAAa,IAAMd,EAAKkB,YAAa,CACtC,MAAMC,QAAiBrC,EAAOc,SAASI,EAAMT,GAE7C,MADAtB,KAAKgC,WAAWI,OAAOQ,GACjBM,CACR,CACD,MAAMvD,CACR,CACJ,CAEA,YAAMwD,CAAOC,GAAa3D,KAAEA,EAAI4D,QAAEA,EAAO/B,SAAEA,IAExC,MAAMH,EAAYkC,EAAQ,gBAAkB,GACtCC,EAASD,EAAQ,aAAe,GAChCE,EAAsBF,EAAQ,aAAe,OAEnD,IAAI3D,QAAmBM,KAAKN,WAAW0D,EAAKE,GAC5C,IAAK5D,EACF,MAAO,CACJmC,OAAQ,IACR2B,QAAS,sBAGf,IAAIC,EAAO/D,EAAW+D,KACtB,MAAMC,EAAiB,MAATD,GAAqC,gBAArBzD,KAAKY,OAAOI,KAC1C,IACG,GAAa,MAATyC,EAAc,CACf,IAAK,CAAC,OAAQ,OAAOE,SAASJ,GAAS,MAAM,IAAI3B,SAAS,iBAAkB,CAAEC,OAAQ,MAC3E,SAAX0B,QACWvD,KAAKR,UAAUC,EAAMC,SACrBM,KAAKa,OAAOpB,EAAMC,EAAYyB,EAAWG,EACtD,CAED,MAAMC,QAAyB3B,EAAAA,QAAO4B,QAAQL,EAAWzB,EAAWI,QAIpE,SAHME,KAAKyB,iBAAiBF,EAAiBJ,UAAWzB,EAAWS,MAG/DoB,EAAiBF,OAASjB,KAAKC,MAAO,MAAM,IAAIuB,SAAS,kBAAmB,CAAEC,OAAQ,MAC1F,IAAIlC,EAAY,KAChB,GAAIF,EACD,GAAIiE,EAAO,CACR,MACME,GADU,IAAIC,aACCC,OAAOrE,GAC5BE,EAAOoE,KAAKC,MAAMJ,EACpB,MACEjE,QAAaC,EAAAA,QAAOC,cAAcJ,EAAMC,EAAWI,cAInDE,KAAKiE,cAAc,CACtBV,SACAE,OACAhE,KAAME,EACNuE,aAAcxE,EAAWwE,aACzBC,OAAQ,CAAA,GACR7C,EACL,CAAC,MAAO8C,GACN,MAAMC,EAAUD,aAAgBlE,MAC1BoE,EAAaF,aAAgBxC,SACnC,IAAI4B,EAAUa,EAAUD,EAAKG,QAAWD,QAAmBF,EAAKR,OAASQ,EACzE,OAAIV,EACM,CACJ7B,OAAQwC,EAAU,KAAOD,aAAI,EAAJA,EAAMvC,SAAU,IACzC2B,QAASO,KAAKS,UAAUhB,IAGvB,CACJ3B,OAAQwC,EAAU,KAAOD,aAAI,EAAJA,EAAMvC,SAAU,IACzC2B,cAAe5D,EAAAA,QAAO6E,cAAcjB,EAAS9D,EAAWI,QAE7D,CAED,OAAI4D,EACM,CACJ7B,OAAQ,IACR2B,QAAS,aAIR,CACJ3B,OAAQ,IACR2B,cAAe5D,EAAAA,QAAO6E,cAAc,YAAa/E,EAAWI,QAElE,EAEF4E,QAAAC,QAAArF"}
package/server/index.mjs CHANGED
@@ -1 +1 @@
1
- import e from"../include/crypto.mjs";import t from"./Base.mjs";import{fileScaner as i}from"../include/FileScaner.mjs";class a extends t{async handshake(t,i){var a,s;const n=await e.decryptBuffer(t,i.secret),o=await this.getSecret();if(!n)throw new Error("Invalid handshake data");if(n.hash!==i.hash)throw new Error("Invalid handshake");if(n.secret!==i.secret)throw new Error("Invalid handshake secret");if(Date.now()-n.clientTime>3e4)throw new Error("Handshake expired");const l=new Date;throw{timeDiffarenc:new Date(n.clientTime).getTime()-l.getTime(),maxFileSize:(null===(a=this.config.upload)||void 0===a?void 0:a.maxFilesize)||null,dev:"development"===this.config.mode,checkFileType:(null===(s=this.config.upload)||void 0===s?void 0:s.checkFileType)||!1,signeture:await e.encrypt({expire:Date.now()+3e4,hash:i.hash},o)}}async upload(t,a,s,n){var o;const l=await e.decryptBuffer(t,a.secret),r=await e.decrypt(s,a.secret);await this.isValidSigneture(r.signeture,a.hash);const d=this.config.upload;if(!(null==d?void 0:d.chunk)||!(null==d?void 0:d.complete))throw new Response("Upload not supported",{status:403});if("failed"===(null==l?void 0:l.type)){const e=this.uploadMeta.get(l.fileid);throw e&&d.failed?(await d.failed(e,n),this.uploadMeta.delete(l.fileid),{success:!0}):new Response("Invalid upload",{status:400})}if("meta"===l.type){if((null==d?void 0:d.maxFilesize)&&l.filesize>1024*d.maxFilesize)throw new Response(`File size exceeds the limit of ${d.maxFilesize} KB`,{status:413});throw this.uploadMeta.set(l.fileid,Object.assign(Object.assign({},l),{expire:Date.now()+36e5})),this.uploadMeta.forEach((e,t)=>{e.expire<Date.now()&&this.uploadMeta.delete(t)}),l}{const{chunk:e,fileId:t,chunkIndex:a}=l,s=this.uploadMeta.get(t);if(!s)throw new Response("Invalid upload meta",{status:400});if(d.checkFileType&&0===a){if(!i(e))throw new Error("Unknown or unsupported file type")}if((null===(o=this.config.upload)||void 0===o?void 0:o.maxFilesize)&&l.filesize>1024*this.config.upload.maxFilesize)throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize/1024} MB`,{status:413});if(await d.chunk(e,{filename:s.filename,filesize:s.filesize,filetype:s.filetype,fileid:s.fileid,totalChunks:s.totalChunks,chunkIndex:a},n),a+1===s.totalChunks){const e=await d.complete(s,n);throw this.uploadMeta.delete(t),e}throw l}}async listen({path:t,body:i,method:a,origin:s,signeture:n},o){let l=await this.clientInfo(t,s);const r="/"!==(t=l.path)&&"development"===this.config.mode;try{if("/"===t){if(!["POST","PUT"].includes(a))throw new Response("Invalid method",{status:405});"POST"===a?await this.handshake(i,l):await this.upload(i,l,n,o)}const s=await e.decrypt(n,l.secret);if(await this.isValidSigneture(s.signeture,l.hash),s.expire<Date.now())throw new Response("Request expired",{status:403});let d=null;if(i)if(r){const e=(new TextDecoder).decode(i);d=JSON.parse(e)}else d=await e.decryptBuffer(i,l.secret);await this.handleRequest({method:a,path:t,body:d,searchParams:l.searchParams,params:{}},o)}catch(t){const i=t instanceof Error,a=t instanceof Response;let s=i?t.message:a?await t.text():t;return r?{status:i?404:(null==t?void 0:t.status)||200,content:JSON.stringify(s)}:{status:i?404:(null==t?void 0:t.status)||200,content:await e.encryptBuffer(s,l.secret)}}return r?{status:404,content:"Not found"}:{status:404,content:await e.encryptBuffer("Not found",l.secret)}}}export{a as default};//# sourceMappingURL=index.mjs.map
1
+ import e from"../include/crypto.mjs";import t from"./Base.mjs";import{fileScaner as i}from"../include/FileScaner.mjs";class a extends t{async handshake(t,i){var a,s;const n=await e.decryptBuffer(t,i.secret),o=await this.getSecret();if(!n)throw new Error("Invalid handshake data");if(n.hash!==i.hash)throw new Error("Invalid handshake");if(n.secret!==i.secret)throw new Error("Invalid handshake secret");if(Date.now()-n.clientTime>3e4)throw new Error("Handshake expired");const l=new Date;throw{timeDiffarenc:new Date(n.clientTime).getTime()-l.getTime(),maxFileSize:(null===(a=this.config.upload)||void 0===a?void 0:a.maxFilesize)||null,dev:"development"===this.config.mode,checkFileType:(null===(s=this.config.upload)||void 0===s?void 0:s.checkFileType)||!1,signeture:await e.encrypt({expire:Date.now()+3e4,hash:i.hash},o)}}async upload(t,a,s,n){var o;const l=await e.decryptBuffer(t,a.secret),r=await e.decrypt(s,a.secret);await this.isValidSigneture(r.signeture,a.hash);const d=this.config.upload;if(!(null==d?void 0:d.chunk)||!(null==d?void 0:d.complete))throw new Response("Upload not supported",{status:403});if("failed"===(null==l?void 0:l.type)){const e=this.uploadMeta.get(l.fileid);throw e&&d.failed?(await d.failed(e,n),this.uploadMeta.delete(l.fileid),{success:!0}):new Response("Invalid upload",{status:400})}if("meta"===l.type){if((null==d?void 0:d.maxFilesize)&&l.filesize>1024*d.maxFilesize)throw new Response(`File size exceeds the limit of ${d.maxFilesize} KB`,{status:413});throw this.uploadMeta.set(l.fileid,Object.assign(Object.assign({},l),{expire:Date.now()+36e5})),this.uploadMeta.forEach((e,t)=>{e.expire<Date.now()&&this.uploadMeta.delete(t)}),l}{const{chunk:e,fileId:t,chunkIndex:a}=l,s=this.uploadMeta.get(t);if(!s)throw new Response("Invalid upload meta",{status:400});if(d.checkFileType&&0===a){if(!i(e))throw new Error("Unknown or unsupported file type")}if((null===(o=this.config.upload)||void 0===o?void 0:o.maxFilesize)&&l.filesize>1024*this.config.upload.maxFilesize)throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize/1024} MB`,{status:413});if(await d.chunk(e,{filename:s.filename,filesize:s.filesize,filetype:s.filetype,fileid:s.fileid,totalChunks:s.totalChunks,chunkIndex:a},n),a+1===s.totalChunks){const e=await d.complete(s,n);throw this.uploadMeta.delete(t),e}throw l}}async listen(t,{body:i,headers:a,metadata:s}){const n=a["x-signeture"]||"",o=a["x-origin"]||"",l=a["x-method"]||"POST";let r=await this.clientInfo(t,o);if(!r)return{status:403,content:"Client not allowed"};let d=r.path;const c="/"!==d&&"development"===this.config.mode;try{if("/"===d){if(!["POST","PUT"].includes(l))throw new Response("Invalid method",{status:405});"POST"===l?await this.handshake(i,r):await this.upload(i,r,n,s)}const t=await e.decrypt(n,r.secret);if(await this.isValidSigneture(t.signeture,r.hash),t.expire<Date.now())throw new Response("Request expired",{status:403});let a=null;if(i)if(c){const e=(new TextDecoder).decode(i);a=JSON.parse(e)}else a=await e.decryptBuffer(i,r.secret);await this.handleRequest({method:l,path:d,body:a,searchParams:r.searchParams,params:{}},s)}catch(t){const i=t instanceof Error,a=t instanceof Response;let s=i?t.message:a?await t.text():t;return c?{status:i?404:(null==t?void 0:t.status)||200,content:JSON.stringify(s)}:{status:i?404:(null==t?void 0:t.status)||200,content:await e.encryptBuffer(s,r.secret)}}return c?{status:404,content:"Not found"}:{status:404,content:await e.encryptBuffer("Not found",r.secret)}}}export{a as default};//# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/server/index.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\r\nimport { ArgsInfo, ListenerInfo, ServerResponse } from \"./types\";\r\nimport SecurequServerBase from \"./Base\";\r\nimport fileScaner from \"../include/FileScaner\";\r\n\r\nclass SecurequServer extends SecurequServerBase {\r\n\r\n async handshake(body: any, clientInfo: any) {\r\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\r\n const serverSecret = await this.getSecret()\r\n if (!data) throw new Error(\"Invalid handshake data\");\r\n if (data.hash !== clientInfo.hash) {\r\n throw new Error(\"Invalid handshake\");\r\n } else if (data.secret !== clientInfo.secret) {\r\n throw new Error(\"Invalid handshake secret\");\r\n } else if (Date.now() - data.clientTime > 30000) { // 30 seconds\r\n throw new Error(\"Handshake expired\");\r\n }\r\n\r\n const serverTime = new Date();\r\n const clientDate = new Date(data.clientTime);\r\n const offsetMs = clientDate.getTime() - serverTime.getTime();\r\n\r\n let info = {\r\n timeDiffarenc: offsetMs,\r\n maxFileSize: this.config.upload?.maxFilesize || null,\r\n dev: this.config.mode === 'development',\r\n checkFileType: this.config.upload?.checkFileType || false,\r\n signeture: await crypto.encrypt({\r\n expire: Date.now() + 30000, // 30 seconds\r\n hash: clientInfo.hash\r\n }, serverSecret)\r\n }\r\n throw info\r\n }\r\n\r\n async upload(body: any, clientInfo: any, signeture: string, args?: ArgsInfo) {\r\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\r\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\r\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\r\n const upload = this.config.upload\r\n\r\n if (!upload?.chunk || !upload?.complete) {\r\n throw new Response(\"Upload not supported\", { status: 403 })\r\n }\r\n\r\n if (data?.type === 'failed') {\r\n const meta = this.uploadMeta.get(data.fileid)\r\n if (meta && upload.failed) {\r\n await upload.failed(meta, args)\r\n this.uploadMeta.delete(data.fileid)\r\n throw { success: true }\r\n } else {\r\n throw new Response(\"Invalid upload\", { status: 400 })\r\n }\r\n } else if (data.type === 'meta') {\r\n if (upload?.maxFilesize && data.filesize > upload.maxFilesize * 1024) {\r\n throw new Response(`File size exceeds the limit of ${upload.maxFilesize} KB`, { status: 413 })\r\n }\r\n this.uploadMeta.set(data.fileid, {\r\n ...data,\r\n expire: Date.now() + 3600000 // 1 hour\r\n })\r\n this.uploadMeta.forEach((meta, key) => {\r\n if (meta.expire < Date.now()) {\r\n this.uploadMeta.delete(key)\r\n }\r\n })\r\n\r\n throw data\r\n } else {\r\n const { chunk, fileId, chunkIndex } = data;\r\n const meta = this.uploadMeta.get(fileId)\r\n if (!meta) {\r\n throw new Response(\"Invalid upload meta\", { status: 400 })\r\n }\r\n if (upload.checkFileType && chunkIndex === 0) {\r\n let fileType = fileScaner(chunk);\r\n if (!fileType) {\r\n throw new Error(\"Unknown or unsupported file type\");\r\n }\r\n }\r\n\r\n if (this.config.upload?.maxFilesize && data.filesize > this.config.upload.maxFilesize * 1024) {\r\n throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize / 1024} MB`, { status: 413 })\r\n }\r\n await upload.chunk(chunk, {\r\n filename: meta.filename,\r\n filesize: meta.filesize,\r\n filetype: meta.filetype,\r\n fileid: meta.fileid,\r\n totalChunks: meta.totalChunks,\r\n chunkIndex,\r\n }, args)\r\n if (chunkIndex + 1 === meta.totalChunks) {\r\n const filepath = await upload.complete(meta, args)\r\n this.uploadMeta.delete(fileId)\r\n throw filepath\r\n }\r\n throw data\r\n }\r\n }\r\n\r\n async listen({ path, body, method, origin, signeture }: ListenerInfo, args?: ArgsInfo): Promise<ServerResponse> {\r\n let clientInfo = await this.clientInfo(path, origin)\r\n path = clientInfo.path\r\n const isDev = path !== '/' && this.config.mode === 'development'\r\n try {\r\n if (path === '/') {\r\n if (!['POST', 'PUT'].includes(method)) throw new Response(\"Invalid method\", { status: 405 });\r\n method === \"POST\"\r\n ? await this.handshake(body, clientInfo)\r\n : await this.upload(body, clientInfo, signeture, args);\r\n }\r\n\r\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\r\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\r\n\r\n // if reques is expired\r\n if (decryptSigneture.expire < Date.now()) throw new Response(\"Request expired\", { status: 403 });\r\n let data: any = null\r\n if (body) {\r\n if (isDev) {\r\n const decoder = new TextDecoder();\r\n const text = decoder.decode(body);\r\n data = JSON.parse(text)\r\n } else {\r\n data = await crypto.decryptBuffer(body, clientInfo.secret)\r\n }\r\n }\r\n\r\n await this.handleRequest({\r\n method,\r\n path,\r\n body: data,\r\n searchParams: clientInfo.searchParams,\r\n params: {}\r\n }, args);\r\n } catch (info: any) {\r\n const isError = info instanceof Error\r\n const isResponse = info instanceof Response\r\n let content = isError ? info.message : (isResponse ? await info.text() : info);\r\n if (path === '/') {\r\n\r\n }\r\n if (isDev) {\r\n return {\r\n status: isError ? 404 : (info?.status || 200),\r\n content: JSON.stringify(content)\r\n };\r\n }\r\n return {\r\n status: isError ? 404 : (info?.status || 200),\r\n content: await crypto.encryptBuffer(content, clientInfo.secret)\r\n };\r\n }\r\n\r\n if (isDev) {\r\n return {\r\n status: 404,\r\n content: \"Not found\"\r\n };\r\n }\r\n\r\n return {\r\n status: 404,\r\n content: await crypto.encryptBuffer(\"Not found\", clientInfo.secret)\r\n };\r\n }\r\n\r\n}\r\n\r\nexport default SecurequServer;"],"names":["SecurequServer","SecurequServerBase","handshake","body","clientInfo","data","crypto","decryptBuffer","secret","serverSecret","this","getSecret","Error","hash","Date","now","clientTime","serverTime","timeDiffarenc","getTime","maxFileSize","_a","config","upload","maxFilesize","dev","mode","checkFileType","_b","signeture","encrypt","expire","args","decryptSigneture","decrypt","isValidSigneture","chunk","complete","Response","status","type","meta","uploadMeta","get","fileid","failed","delete","success","filesize","set","Object","assign","forEach","key","fileId","chunkIndex","fileScaner","filename","filetype","totalChunks","filepath","listen","path","method","origin","isDev","includes","text","TextDecoder","decode","JSON","parse","handleRequest","searchParams","params","info","isError","isResponse","content","message","stringify","encryptBuffer"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/server/index.ts"],"sourcesContent":["import crypto from \"../include/crypto\";\nimport { Metadata, ListenerInfo, ServerResponse } from \"./types\";\nimport SecurequServerBase from \"./Base\";\nimport fileScaner from \"../include/FileScaner\";\nimport { HTTPMethods } from \"../client/types\";\n\nclass SecurequServer extends SecurequServerBase {\n\n async handshake(body: any, clientInfo: any) {\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\n const serverSecret = await this.getSecret()\n if (!data) throw new Error(\"Invalid handshake data\");\n if (data.hash !== clientInfo.hash) {\n throw new Error(\"Invalid handshake\");\n } else if (data.secret !== clientInfo.secret) {\n throw new Error(\"Invalid handshake secret\");\n } else if (Date.now() - data.clientTime > 30000) { // 30 seconds\n throw new Error(\"Handshake expired\");\n }\n\n const serverTime = new Date();\n const clientDate = new Date(data.clientTime);\n const offsetMs = clientDate.getTime() - serverTime.getTime();\n\n let info = {\n timeDiffarenc: offsetMs,\n maxFileSize: this.config.upload?.maxFilesize || null,\n dev: this.config.mode === 'development',\n checkFileType: this.config.upload?.checkFileType || false,\n signeture: await crypto.encrypt({\n expire: Date.now() + 30000, // 30 seconds\n hash: clientInfo.hash\n }, serverSecret)\n }\n throw info\n }\n\n async upload(body: any, clientInfo: any, signeture: string, metadata?: Metadata) {\n const data: any = await crypto.decryptBuffer(body, clientInfo.secret)\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\n const upload = this.config.upload\n\n if (!upload?.chunk || !upload?.complete) {\n throw new Response(\"Upload not supported\", { status: 403 })\n }\n\n if (data?.type === 'failed') {\n const meta = this.uploadMeta.get(data.fileid)\n if (meta && upload.failed) {\n await upload.failed(meta, metadata)\n this.uploadMeta.delete(data.fileid)\n throw { success: true }\n } else {\n throw new Response(\"Invalid upload\", { status: 400 })\n }\n } else if (data.type === 'meta') {\n if (upload?.maxFilesize && data.filesize > upload.maxFilesize * 1024) {\n throw new Response(`File size exceeds the limit of ${upload.maxFilesize} KB`, { status: 413 })\n }\n this.uploadMeta.set(data.fileid, {\n ...data,\n expire: Date.now() + 3600000 // 1 hour\n })\n this.uploadMeta.forEach((meta, key) => {\n if (meta.expire < Date.now()) {\n this.uploadMeta.delete(key)\n }\n })\n\n throw data\n } else {\n const { chunk, fileId, chunkIndex } = data;\n const meta = this.uploadMeta.get(fileId)\n if (!meta) {\n throw new Response(\"Invalid upload meta\", { status: 400 })\n }\n if (upload.checkFileType && chunkIndex === 0) {\n let fileType = fileScaner(chunk);\n if (!fileType) {\n throw new Error(\"Unknown or unsupported file type\");\n }\n }\n\n if (this.config.upload?.maxFilesize && data.filesize > this.config.upload.maxFilesize * 1024) {\n throw new Response(`File size exceeds the limit of ${this.config.upload.maxFilesize / 1024} MB`, { status: 413 })\n }\n await upload.chunk(chunk, {\n filename: meta.filename,\n filesize: meta.filesize,\n filetype: meta.filetype,\n fileid: meta.fileid,\n totalChunks: meta.totalChunks,\n chunkIndex,\n }, metadata)\n if (chunkIndex + 1 === meta.totalChunks) {\n const filepath = await upload.complete(meta, metadata)\n this.uploadMeta.delete(fileId)\n throw filepath\n }\n throw data\n }\n }\n\n async listen(url: string, { body, headers, metadata }: ListenerInfo): Promise<ServerResponse> {\n\n const signeture = headers['x-signeture'] || '';\n const origin = headers['x-origin'] || '';\n const method: HTTPMethods = headers['x-method'] || 'POST' as any\n\n let clientInfo = await this.clientInfo(url, origin)\n if (!clientInfo) {\n return {\n status: 403,\n content: \"Client not allowed\"\n }\n }\n let path = clientInfo.path\n const isDev = path !== '/' && this.config.mode === 'development'\n try {\n if (path === '/') {\n if (!['POST', 'PUT'].includes(method)) throw new Response(\"Invalid method\", { status: 405 });\n method === \"POST\"\n ? await this.handshake(body, clientInfo)\n : await this.upload(body, clientInfo, signeture, metadata);\n }\n\n const decryptSigneture = await crypto.decrypt(signeture, clientInfo.secret) as any\n await this.isValidSigneture(decryptSigneture.signeture, clientInfo.hash)\n\n // if reques is expired\n if (decryptSigneture.expire < Date.now()) throw new Response(\"Request expired\", { status: 403 });\n let data: any = null\n if (body) {\n if (isDev) {\n const decoder = new TextDecoder();\n const text = decoder.decode(body);\n data = JSON.parse(text)\n } else {\n data = await crypto.decryptBuffer(body, clientInfo.secret)\n }\n }\n\n await this.handleRequest({\n method,\n path,\n body: data,\n searchParams: clientInfo.searchParams,\n params: {}\n }, metadata);\n } catch (info: any) {\n const isError = info instanceof Error\n const isResponse = info instanceof Response\n let content = isError ? info.message : (isResponse ? await info.text() : info);\n if (isDev) {\n return {\n status: isError ? 404 : (info?.status || 200),\n content: JSON.stringify(content)\n };\n }\n return {\n status: isError ? 404 : (info?.status || 200),\n content: await crypto.encryptBuffer(content, clientInfo.secret)\n };\n }\n\n if (isDev) {\n return {\n status: 404,\n content: \"Not found\"\n };\n }\n\n return {\n status: 404,\n content: await crypto.encryptBuffer(\"Not found\", clientInfo.secret)\n };\n }\n\n}\n\nexport default SecurequServer;"],"names":["SecurequServer","SecurequServerBase","handshake","body","clientInfo","data","crypto","decryptBuffer","secret","serverSecret","this","getSecret","Error","hash","Date","now","clientTime","serverTime","timeDiffarenc","getTime","maxFileSize","_a","config","upload","maxFilesize","dev","mode","checkFileType","_b","signeture","encrypt","expire","metadata","decryptSigneture","decrypt","isValidSigneture","chunk","complete","Response","status","type","meta","uploadMeta","get","fileid","failed","delete","success","filesize","set","Object","assign","forEach","key","fileId","chunkIndex","fileScaner","filename","filetype","totalChunks","filepath","listen","url","headers","origin","method","content","path","isDev","includes","text","TextDecoder","decode","JSON","parse","handleRequest","searchParams","params","info","isError","isResponse","message","stringify","encryptBuffer"],"mappings":"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"}
package/server/types.d.ts CHANGED
@@ -1,77 +1,77 @@
1
1
  import { MatchFunction } from 'path-to-regexp';
2
2
  import { HTTPMethods } from '../client/types.js';
3
3
 
4
- type ServerClientSecret = string;
5
- type ServerClientOrigin = string;
6
- type ServerClientInfo = {
7
- path: string;
8
- secret: string;
9
- hash: string;
10
- searchParams: {
11
- [key: string]: any;
12
- };
13
- };
14
- type ServerClient = {
15
- origin: string;
16
- secret: ServerClientSecret;
17
- };
18
- type UploadFileMeta = {
19
- filename: string;
20
- filesize: number;
21
- filetype: string;
22
- fileid: string;
23
- chunkIndex: number;
24
- totalChunks: number;
25
- };
26
- type UploadFilePath = string;
27
- type ArgsInfo = {
28
- [key: string]: any;
29
- };
30
- type SecurequServerConfig = {
31
- mode: "production" | "development";
32
- basepath: string;
33
- clients: ServerClient[];
34
- upload?: {
35
- maxFilesize?: number;
36
- checkFileType?: boolean;
37
- chunk: (chunk: Uint8Array, meta: UploadFileMeta, args?: ArgsInfo) => Promise<boolean>;
38
- complete: (meta: UploadFileMeta, args?: ArgsInfo) => Promise<UploadFilePath>;
39
- failed?: (meta: UploadFileMeta, args?: ArgsInfo) => Promise<boolean>;
40
- };
41
- accept?: (info: HandlerInfo, args?: ArgsInfo) => boolean | Promise<boolean>;
42
- };
43
- type ListenerInfo = {
44
- signeture: string;
45
- path: string;
46
- body: any;
47
- method: HTTPMethods;
48
- origin: string;
49
- };
50
- type HandlerInfo = {
51
- path: string;
52
- body: object;
53
- method: HTTPMethods;
54
- searchParams: {
55
- [key: string]: any;
56
- };
57
- params: {
58
- [key: string]: any;
59
- };
60
- };
61
- type ServerResponse = {
62
- content: Uint8Array | string;
63
- status: number;
64
- };
65
- type HandlerFunction = (info: HandlerInfo, args?: any) => (any | void) | Promise<Partial<any> | void>;
66
- type RouteFactory = {
67
- [key in HTTPMethods]: {
68
- [path: string]: {
69
- handler: HandlerFunction;
70
- test: MatchFunction<{
71
- [key: string]: string;
72
- }>;
73
- };
74
- };
4
+ type ServerClientSecret = string;
5
+ type ServerClientOrigin = string;
6
+ type ServerClientInfo = {
7
+ path: string;
8
+ secret: string;
9
+ hash: string;
10
+ searchParams: {
11
+ [key: string]: any;
12
+ };
13
+ };
14
+ type ServerClient = {
15
+ origin: string;
16
+ secret: ServerClientSecret;
17
+ };
18
+ type UploadFileMeta = {
19
+ filename: string;
20
+ filesize: number;
21
+ filetype: string;
22
+ fileid: string;
23
+ chunkIndex: number;
24
+ totalChunks: number;
25
+ };
26
+ type UploadFilePath = string;
27
+ type Metadata = {
28
+ [key: string]: any;
29
+ };
30
+ type SecurequServerConfig = {
31
+ mode?: "production" | "development";
32
+ basepath: string;
33
+ clients: ServerClient[];
34
+ upload?: {
35
+ maxFilesize?: number;
36
+ checkFileType?: boolean;
37
+ chunk: (chunk: Uint8Array, uploadMeta: UploadFileMeta, metadata?: Metadata) => Promise<boolean>;
38
+ complete: (meta: UploadFileMeta, metadata?: Metadata) => Promise<UploadFilePath>;
39
+ failed?: (meta: UploadFileMeta, metadata?: Metadata) => Promise<boolean>;
40
+ };
41
+ accept?: (info: HandlerInfo, metadata?: Metadata) => boolean | Promise<boolean>;
42
+ };
43
+ type ListenerInfo = {
44
+ body: any;
45
+ headers: {
46
+ [key: string]: string;
47
+ };
48
+ metadata?: Metadata;
49
+ };
50
+ type HandlerInfo = {
51
+ path: string;
52
+ body: object;
53
+ method: HTTPMethods;
54
+ searchParams: {
55
+ [key: string]: any;
56
+ };
57
+ params: {
58
+ [key: string]: any;
59
+ };
60
+ };
61
+ type ServerResponse = {
62
+ content: Uint8Array | string;
63
+ status: number;
64
+ };
65
+ type HandlerFunction = (info: HandlerInfo, metadata?: Metadata) => (any | void) | Promise<Partial<any> | void>;
66
+ type RouteFactory = {
67
+ [key in HTTPMethods]: {
68
+ [path: string]: {
69
+ handler: HandlerFunction;
70
+ test: MatchFunction<{
71
+ [key: string]: string;
72
+ }>;
73
+ };
74
+ };
75
75
  };
76
76
 
77
- export type { ArgsInfo, HandlerFunction, HandlerInfo, ListenerInfo, RouteFactory, SecurequServerConfig, ServerClient, ServerClientInfo, ServerClientOrigin, ServerClientSecret, ServerResponse, UploadFileMeta, UploadFilePath };
77
+ export type { HandlerFunction, HandlerInfo, ListenerInfo, Metadata, RouteFactory, SecurequServerConfig, ServerClient, ServerClientInfo, ServerClientOrigin, ServerClientSecret, ServerResponse, UploadFileMeta, UploadFilePath };