@stefanobalocco/honosignedrequests 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -145,7 +145,9 @@ These are specific to the in-memory implementation:
|
|
|
145
145
|
|
|
146
146
|
```html
|
|
147
147
|
<script type="module">
|
|
148
|
-
import
|
|
148
|
+
import SignedRequester from 'https://cdn.jsdelivr.net/gh/StefanoBalocco/HonoSignedRequests@1.2.0/client/dist/SignedRequester.min.js';
|
|
149
|
+
// Named import also works:
|
|
150
|
+
// import { SignedRequester } from 'https://cdn.jsdelivr.net/gh/StefanoBalocco/HonoSignedRequests@1.2.0/client/dist/SignedRequester.min.js';
|
|
149
151
|
|
|
150
152
|
const requester = new SignedRequester();
|
|
151
153
|
// You can also specify a base URL for requests
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function t(t,s){let i;if(0<t?.length&&e.test(t)){const e=t.length%4,o=(0===e?t:t.padEnd(t.length+(4-e),"=")).replace(/-/g,"+").replace(/_/g,"/");try{const t=atob(o);i=Uint8Array.from(t,t=>t.charCodeAt(0))}catch(t){s?.(t)}}return i}const e=/^(?=.)(?:[A-Za-z0-9\-_]{4})*(?:[A-Za-z0-9\-_]{2}(?:==)?|[A-Za-z0-9\-_]{3}=?)?$/;class s{t(t=!0){let e=Promise.resolve(!1);return this.i?t&&(e=new Promise(t=>{this.o.push(t)})):(this.i=!0,e=Promise.resolve(!0)),e}h(){if(this.i)if(0<this.o.length){const t=this.o.shift();t&&t(!0)}else this.i=!1}l(){void 0!==this.u&&(this.u++,localStorage.setItem("sequenceNumber",this.u.toString()))}S(){let e=!1;const s=localStorage.getItem("sessionId"),i=localStorage.getItem("token"),o=localStorage.getItem("sequenceNumber");if(s&&i&&o){const r=parseInt(s),n=parseInt(o),a=t(i,this.m);isNaN(r)||isNaN(n)||!a||(this.p=r,this.N=a,this.u=n,e=!0)}return e}constructor(t,e){this.i=!1,this.o=[],this.v=t,this.m=e}setSession(e){const s=t(e.token,this.m);if(!s)throw new Error("Invalid token format");this.p=e.sessionId,this.N=s,this.u=e.sequenceNumber,localStorage.setItem("sessionId",e.sessionId.toString()),localStorage.setItem("token",e.token),localStorage.setItem("sequenceNumber",e.sequenceNumber.toString())}getSession(){let t;return t=void 0!==this.p&&void 0!==this.N&&void 0!==this.u||this.S(),t}clearSession(){localStorage.removeItem("sessionId"),localStorage.removeItem("token"),localStorage.removeItem("sequenceNumber"),this.p=void 0,this.N=void 0,this.u=void 0}async signedRequest(t,e,i={}){let o,r;await this.t();try{if(void 0!==this.p&&void 0!==this.N&&void 0!==this.u){const r=Date.now(),n=Object.entries(e),a=[["sessionId",this.p],["sequenceNumber",this.u],["timestamp",r],...n.sort((t,e)=>t[0].localeCompare(e[0]))].map(([t,e])=>`${t}=${s.q.has(typeof e)||null===e?String(e):JSON.stringify(e)}`).join(";"),h=await crypto.subtle.importKey("raw",this.N,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),c=new TextEncoder,l=await crypto.subtle.sign("HMAC",h,c.encode(a)),u=function(t,e){let s="";if(0<t?.length)try{const e=Array.from(t,t=>String.fromCharCode(t)).join("");s=btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(t){e?.(t)}return s}(new Uint8Array(l),this.m),d={sessionId:this.p,timestamp:r,signature:u};Object.assign(d,Object.fromEntries(n));const g=i.baseUrl?`${i.baseUrl}${t}`:this.v?`${this.v}${t}`:t,S=i.method||"POST";o=await fetch(g,{method:S,headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify(d)}),o.ok?this.l():401===o.status&&this.clearSession()}else r=new Error("Session not configured")}catch(t){r=t instanceof Error?t:new Error(String(t))}finally{this.h()}if(r)throw r;return o}async signedRequestJson(t,e,s={}){let i,o;try{const r=await this.signedRequest(t,e,s);r.ok?i=await r.json():o=new Error(`Request failed with status ${r.status}`)}catch(t){o=t instanceof Error?t:new Error(String(t))}if(o)throw o;return i}}s.q=new Set(["undefined","string","number"]);export{s as SignedRequester};
|
|
1
|
+
function t(t,s){let i;if(0<t?.length&&e.test(t)){const e=t.length%4,o=(0===e?t:t.padEnd(t.length+(4-e),"=")).replace(/-/g,"+").replace(/_/g,"/");try{const t=atob(o);i=Uint8Array.from(t,t=>t.charCodeAt(0))}catch(t){s?.(t)}}return i}const e=/^(?=.)(?:[A-Za-z0-9\-_]{4})*(?:[A-Za-z0-9\-_]{2}(?:==)?|[A-Za-z0-9\-_]{3}=?)?$/;class s{t(t=!0){let e=Promise.resolve(!1);return this.i?t&&(e=new Promise(t=>{this.o.push(t)})):(this.i=!0,e=Promise.resolve(!0)),e}h(){if(this.i)if(0<this.o.length){const t=this.o.shift();t&&t(!0)}else this.i=!1}l(){void 0!==this.u&&(this.u++,localStorage.setItem("sequenceNumber",this.u.toString()))}S(){let e=!1;const s=localStorage.getItem("sessionId"),i=localStorage.getItem("token"),o=localStorage.getItem("sequenceNumber");if(s&&i&&o){const r=parseInt(s),n=parseInt(o),a=t(i,this.m);isNaN(r)||isNaN(n)||!a||(this.p=r,this.N=a,this.u=n,e=!0)}return e}constructor(t,e){this.i=!1,this.o=[],this.v=t,this.m=e}setSession(e){const s=t(e.token,this.m);if(!s)throw new Error("Invalid token format");this.p=e.sessionId,this.N=s,this.u=e.sequenceNumber,localStorage.setItem("sessionId",e.sessionId.toString()),localStorage.setItem("token",e.token),localStorage.setItem("sequenceNumber",e.sequenceNumber.toString())}getSession(){let t;return t=void 0!==this.p&&void 0!==this.N&&void 0!==this.u||this.S(),t}clearSession(){localStorage.removeItem("sessionId"),localStorage.removeItem("token"),localStorage.removeItem("sequenceNumber"),this.p=void 0,this.N=void 0,this.u=void 0}async signedRequest(t,e,i={}){let o,r;await this.t();try{if(void 0!==this.p&&void 0!==this.N&&void 0!==this.u){const r=Date.now(),n=Object.entries(e),a=[["sessionId",this.p],["sequenceNumber",this.u],["timestamp",r],...n.sort((t,e)=>t[0].localeCompare(e[0]))].map(([t,e])=>`${t}=${s.q.has(typeof e)||null===e?String(e):JSON.stringify(e)}`).join(";"),h=await crypto.subtle.importKey("raw",this.N,{name:"HMAC",hash:"SHA-256"},!1,["sign"]),c=new TextEncoder,l=await crypto.subtle.sign("HMAC",h,c.encode(a)),u=function(t,e){let s="";if(0<t?.length)try{const e=Array.from(t,t=>String.fromCharCode(t)).join("");s=btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}catch(t){e?.(t)}return s}(new Uint8Array(l),this.m),d={sessionId:this.p,timestamp:r,signature:u};Object.assign(d,Object.fromEntries(n));const g=i.baseUrl?`${i.baseUrl}${t}`:this.v?`${this.v}${t}`:t,S=i.method||"POST";o=await fetch(g,{method:S,headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify(d)}),o.ok?this.l():401===o.status&&this.clearSession()}else r=new Error("Session not configured")}catch(t){r=t instanceof Error?t:new Error(String(t))}finally{this.h()}if(r)throw r;return o}async signedRequestJson(t,e,s={}){let i,o;try{const r=await this.signedRequest(t,e,s);r.ok?i=await r.json():o=new Error(`Request failed with status ${r.status}`)}catch(t){o=t instanceof Error?t:new Error(String(t))}if(o)throw o;return i}}s.q=new Set(["undefined","string","number"]);export{s as SignedRequester};export default s;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stefanobalocco/honosignedrequests",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "An hono middleware to manage signed requests, including a client implementation.",
|
|
5
5
|
"author": "Stefano Balocco <stefano.balocco@gmail.com>",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -25,13 +25,6 @@
|
|
|
25
25
|
"import": "./client/dist/SignedRequester.min.js"
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "npm run build:server && npm run build:client && npm run build:tests",
|
|
30
|
-
"build:server": "tsc",
|
|
31
|
-
"build:client": "tsc -p client/tsconfig.json && terser client/dist/SignedRequester.js -o client/dist/SignedRequester.min.js --toplevel -m -c --mangle-props regex=/^_/",
|
|
32
|
-
"build:tests": "tsc -p tests/tsconfig.json",
|
|
33
|
-
"run:tests": "npx ava tests/dist/*.test.js --verbose"
|
|
34
|
-
},
|
|
35
28
|
"devDependencies": {
|
|
36
29
|
"@hono/node-server": "^1.13.7",
|
|
37
30
|
"@types/node": "^22.10.5",
|
|
@@ -56,5 +49,12 @@
|
|
|
56
49
|
"signed-requests",
|
|
57
50
|
"session",
|
|
58
51
|
"authentication"
|
|
59
|
-
]
|
|
60
|
-
|
|
52
|
+
],
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "npm run build:server && npm run build:client && npm run build:tests",
|
|
55
|
+
"build:server": "tsc",
|
|
56
|
+
"build:client": "tsc -p client/tsconfig.json && terser client/dist/SignedRequester.js -o client/dist/SignedRequester.min.js --toplevel -m -c --mangle-props regex=/^_/",
|
|
57
|
+
"build:tests": "tsc -p tests/tsconfig.json",
|
|
58
|
+
"run:tests": "npx ava tests/dist/*.test.js --verbose"
|
|
59
|
+
}
|
|
60
|
+
}
|