From 201a18041b044123117ed94f29116cddfb456b25 Mon Sep 17 00:00:00 2001 From: Kenji Urushima Date: Tue, 7 May 2024 19:44:07 +0900 Subject: [PATCH] 0.1.0 release --- CHANGELOG.md | 9 + README.md | 15 +- biome.json | 10 + build.mts | 55 ++ docs/.nojekyll | 1 + docs/assets/highlight.css | 85 ++ docs/assets/icons.js | 15 + docs/assets/icons.svg | 1 + docs/assets/main.js | 59 ++ docs/assets/navigation.js | 1 + docs/assets/search.js | 1 + docs/assets/style.css | 1412 +++++++++++++++++++++++++++ docs/functions/getHMACKey.html | 10 + docs/functions/getNewHMACKey.html | 14 + docs/functions/getSecureRandom.html | 9 + docs/functions/hashab.html | 7 + docs/functions/hashhex.html | 7 + docs/functions/hashrstr.html | 7 + docs/functions/hashutf8.html | 7 + docs/functions/importPEM.html | 9 + docs/functions/sigAlgToHashAlg.html | 1 + docs/functions/sigRStoASN1.html | 13 + docs/functions/signHMACHex.html | 9 + docs/functions/signHex.html | 9 + docs/functions/verifyHMACHex.html | 10 + docs/functions/verifyHex.html | 11 + docs/index.html | 17 +- docs/modules.html | 15 + package.json | 77 ++ src/index.cts | 1 + src/index.mts | 384 ++++++++ src/index.test.mts | 412 ++++++++ tsconfig.build.base.json | 9 + tsconfig.build.cjs.json | 9 + tsconfig.build.esm.json | 8 + tsconfig.json | 22 + tsconfig.typedoc.json | 7 + typedoc.json | 21 + 38 files changed, 2762 insertions(+), 7 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 biome.json create mode 100644 build.mts create mode 100644 docs/.nojekyll create mode 100644 docs/assets/highlight.css create mode 100644 docs/assets/icons.js create mode 100644 docs/assets/icons.svg create mode 100644 docs/assets/main.js create mode 100644 docs/assets/navigation.js create mode 100644 docs/assets/search.js create mode 100644 docs/assets/style.css create mode 100644 docs/functions/getHMACKey.html create mode 100644 docs/functions/getNewHMACKey.html create mode 100644 docs/functions/getSecureRandom.html create mode 100644 docs/functions/hashab.html create mode 100644 docs/functions/hashhex.html create mode 100644 docs/functions/hashrstr.html create mode 100644 docs/functions/hashutf8.html create mode 100644 docs/functions/importPEM.html create mode 100644 docs/functions/sigAlgToHashAlg.html create mode 100644 docs/functions/sigRStoASN1.html create mode 100644 docs/functions/signHMACHex.html create mode 100644 docs/functions/signHex.html create mode 100644 docs/functions/verifyHMACHex.html create mode 100644 docs/functions/verifyHex.html create mode 100644 docs/modules.html create mode 100644 package.json create mode 100644 src/index.cts create mode 100644 src/index.mts create mode 100644 src/index.test.mts create mode 100644 tsconfig.build.base.json create mode 100644 tsconfig.build.cjs.json create mode 100644 tsconfig.build.esm.json create mode 100644 tsconfig.json create mode 100644 tsconfig.typedoc.json create mode 100644 typedoc.json diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..72b0223 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# ChangeLog + +## [0.1.0] - 2024-05-07 + +- initial beta release + +### Added + +- functions and types for initial beta release inherited from jsrsasign diff --git a/README.md b/README.md index 83e2705..b4d50bc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ -# typepki-webcrypto -W3C WebCrypto API helper sub module for TypePKI library +typepki-webcrypto: W3C Web Crypto API helper function sub module for TypePKI library +==================================================================================== + +The 'TypePKI' library is an opensource free TypeScript PKI library which is the successor of the long lived [jsrsasign](https://kjur.github.io/jsrsasign) library. + +The 'typepki-webcrypto' is W3C Web Crypto API [[1]](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API)[[2]](https://www.w3.org/TR/WebCryptoAPI/) helper function sub module for TypePKI library. + +## FEATURE +- easy use for + - keypair generation + - key import + - key export +- Dual CommonJS/ES module package supporting CommonJS(CJS) and ES modules diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..722cfe6 --- /dev/null +++ b/biome.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.4.0/schema.json", + "files": { + "include": ["*.*ts", "**/*.*ts", "*.json"], + "ignore": ["dist"] + }, + "formatter": { + "indentStyle": "space" + } +} diff --git a/build.mts b/build.mts new file mode 100644 index 0000000..2f38224 --- /dev/null +++ b/build.mts @@ -0,0 +1,55 @@ +import * as esbuild from "esbuild"; + +const targetBasePath = `${import.meta.dir ?? "."}/src`; +const distBasePath = `${import.meta.dir ?? "."}/dist`; + +// path from base directory without extension +const files = ["index"]; + +function entrypoints(files: string[], extension: "ts" | "mts" | "cts") { + return files.map((v) => `${targetBasePath}/${v}.${extension}`); +} + +const esms = entrypoints(files, "mts"); +const cjss = entrypoints(files, "cts"); + +await Promise.all([ + // Bun.build({ + // entrypoints: esms, + // outdir: `${distBasePath}/import`, + // target: "node", + // format: "esm", + // splitting: true, + // minify: true, + // naming: "[dir]/[name].m[ext]", + // }) + // .then(console.info) + // .catch(console.error), + esbuild + .build({ + entryPoints: esms, + bundle: true, + minify: true, + splitting: true, + outdir: `${distBasePath}/import`, + platform: "neutral", + format: "esm", + target: "esnext", + outExtension: { ".js": ".mjs" }, + }) + .then(console.info) + .catch(console.error), + esbuild + .build({ + entryPoints: cjss, + bundle: true, + minify: true, + outdir: `${distBasePath}/require`, + platform: "node", + format: "cjs", + target: "esnext", + outExtension: { ".js": ".cjs" }, + }) + .then(console.info) + .catch(console.error), +]); diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e2ac661 --- /dev/null +++ b/docs/.nojekyll @@ -0,0 +1 @@ +TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/docs/assets/highlight.css b/docs/assets/highlight.css new file mode 100644 index 0000000..45f5aca --- /dev/null +++ b/docs/assets/highlight.css @@ -0,0 +1,85 @@ +:root { + --light-hl-0: #AF00DB; + --dark-hl-0: #C586C0; + --light-hl-1: #000000; + --dark-hl-1: #D4D4D4; + --light-hl-2: #795E26; + --dark-hl-2: #DCDCAA; + --light-hl-3: #A31515; + --dark-hl-3: #CE9178; + --light-hl-4: #001080; + --dark-hl-4: #9CDCFE; + --light-hl-5: #098658; + --dark-hl-5: #B5CEA8; + --light-hl-6: #EE0000; + --dark-hl-6: #D7BA7D; + --light-hl-7: #0000FF; + --dark-hl-7: #569CD6; + --light-hl-8: #CD3131; + --dark-hl-8: #F44747; + --light-code-background: #FFFFFF; + --dark-code-background: #1E1E1E; +} + +@media (prefers-color-scheme: light) { :root { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --code-background: var(--light-code-background); +} } + +@media (prefers-color-scheme: dark) { :root { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --code-background: var(--dark-code-background); +} } + +:root[data-theme='light'] { + --hl-0: var(--light-hl-0); + --hl-1: var(--light-hl-1); + --hl-2: var(--light-hl-2); + --hl-3: var(--light-hl-3); + --hl-4: var(--light-hl-4); + --hl-5: var(--light-hl-5); + --hl-6: var(--light-hl-6); + --hl-7: var(--light-hl-7); + --hl-8: var(--light-hl-8); + --code-background: var(--light-code-background); +} + +:root[data-theme='dark'] { + --hl-0: var(--dark-hl-0); + --hl-1: var(--dark-hl-1); + --hl-2: var(--dark-hl-2); + --hl-3: var(--dark-hl-3); + --hl-4: var(--dark-hl-4); + --hl-5: var(--dark-hl-5); + --hl-6: var(--dark-hl-6); + --hl-7: var(--dark-hl-7); + --hl-8: var(--dark-hl-8); + --code-background: var(--dark-code-background); +} + +.hl-0 { color: var(--hl-0); } +.hl-1 { color: var(--hl-1); } +.hl-2 { color: var(--hl-2); } +.hl-3 { color: var(--hl-3); } +.hl-4 { color: var(--hl-4); } +.hl-5 { color: var(--hl-5); } +.hl-6 { color: var(--hl-6); } +.hl-7 { color: var(--hl-7); } +.hl-8 { color: var(--hl-8); } +pre, code { background: var(--code-background); } diff --git a/docs/assets/icons.js b/docs/assets/icons.js new file mode 100644 index 0000000..b79c9e8 --- /dev/null +++ b/docs/assets/icons.js @@ -0,0 +1,15 @@ +(function(svg) { + svg.innerHTML = ``; + svg.style.display = 'none'; + if (location.protocol === 'file:') { + if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', updateUseElements); + else updateUseElements() + function updateUseElements() { + document.querySelectorAll('use').forEach(el => { + if (el.getAttribute('href').includes('#icon-')) { + el.setAttribute('href', el.getAttribute('href').replace(/.*#/, '#')); + } + }); + } + } +})(document.body.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))) \ No newline at end of file diff --git a/docs/assets/icons.svg b/docs/assets/icons.svg new file mode 100644 index 0000000..7dead61 --- /dev/null +++ b/docs/assets/icons.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/main.js b/docs/assets/main.js new file mode 100644 index 0000000..d6f1388 --- /dev/null +++ b/docs/assets/main.js @@ -0,0 +1,59 @@ +"use strict"; +"use strict";(()=>{var Ce=Object.create;var ne=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var Me=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Fe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(t,i)&&i!==n&&ne(t,i,{get:()=>e[i],enumerable:!(r=Pe(e,i))||r.enumerable});return t};var De=(t,e,n)=>(n=t!=null?Ce(_e(t)):{},Fe(e||!t||!t.__esModule?ne(n,"default",{value:t,enumerable:!0}):n,t));var ae=Me((se,oe)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),y=s.str.charAt(1),p;y in s.node.edges?p=s.node.edges[y]:(p=new t.TokenSet,s.node.edges[y]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof se=="object"?oe.exports=n():e.lunr=n()}(this,function(){return t})})()});var re=[];function G(t,e){re.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){re.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(console.log("Show page"),document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){console.log("Scorlling");let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!e.checkVisibility()){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(n&&n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let r=document.createElement("p");r.classList.add("warning"),r.textContent="This member is normally hidden due to your filter settings.",n.prepend(r)}}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent="Copied!",e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent="Copy"},100)},1e3)})})}};var ie=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var de=De(ae());async function le(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=de.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function he(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{le(e,t)}),le(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");let s=!1;i.addEventListener("mousedown",()=>s=!0),i.addEventListener("mouseup",()=>{s=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{s||(s=!1,t.classList.remove("has-focus"))}),Ae(t,i,r,e)}function Ae(t,e,n,r){n.addEventListener("input",ie(()=>{Ve(t,e,n,r)},200));let i=!1;n.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ne(e,n):s.key=="Escape"?n.blur():s.key=="ArrowUp"?ue(e,-1):s.key==="ArrowDown"?ue(e,1):i=!1}),n.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!n.matches(":focus")&&s.key==="/"&&(n.focus(),s.preventDefault())})}function Ve(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=ce(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` + ${ce(l.parent,i)}.${d}`);let y=document.createElement("li");y.classList.value=l.classes??"";let p=document.createElement("a");p.href=r.base+l.url,p.innerHTML=u+d,y.append(p),e.appendChild(y)}}function ue(t,e){let n=t.querySelector(".current");if(!n)n=t.querySelector(e==1?"li:first-child":"li:last-child"),n&&n.classList.add("current");else{let r=n;if(e===1)do r=r.nextElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);else do r=r.previousElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);r&&(n.classList.remove("current"),r.classList.add("current"))}}function Ne(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),e.blur()}}function ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(K(t.substring(s,o)),`${K(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(K(t.substring(s))),i.join("")}var He={"&":"&","<":"<",">":">","'":"'",'"':"""};function K(t){return t.replace(/[&<>"'"]/g,e=>He[e])}var I=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",fe="mousemove",H="mouseup",J={x:0,y:0},pe=!1,ee=!1,Be=!1,D=!1,me=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(me?"is-mobile":"not-mobile");me&&"ontouchstart"in document.documentElement&&(Be=!0,F="touchstart",fe="touchmove",H="touchend");document.addEventListener(F,t=>{ee=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(fe,t=>{if(ee&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(H,()=>{ee=!1});document.addEventListener("click",t=>{pe&&(t.preventDefault(),t.stopImmediatePropagation(),pe=!1)});var X=class extends I{constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(H,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(F,n=>this.onDocumentPointerDown(n)),document.addEventListener(H,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var te;try{te=localStorage}catch{te={getItem(){return null},setItem(){}}}var Q=te;var ye=document.head.appendChild(document.createElement("style"));ye.dataset.for="filters";var Y=class extends I{constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ye.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } +`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=Q.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){Q.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var Z=class extends I{constructor(e){super(e),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let r=this.summary.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function ge(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,ve(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),ve(t.value)})}function ve(t){document.documentElement.dataset.theme=t}var Le;function be(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",xe),xe())}async function xe(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();Le=t.dataset.base+"/",t.innerHTML="";for(let s of i)we(s,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function we(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-index-accordion`:"tsd-index-accordion",s.dataset.key=i.join("$");let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.innerHTML='',Ee(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)we(u,l,i)}else Ee(t,r,t.class)}function Ee(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=Le+t.path,n&&(r.className=n),location.pathname===r.pathname&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else e.appendChild(document.createElement("span")).textContent=t.text}G(X,"a[data-toggle]");G(Z,".tsd-index-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Se=document.getElementById("tsd-theme");Se&&ge(Se);var je=new U;Object.defineProperty(window,"app",{value:je});he();be();})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/docs/assets/navigation.js b/docs/assets/navigation.js new file mode 100644 index 0000000..d87487c --- /dev/null +++ b/docs/assets/navigation.js @@ -0,0 +1 @@ +window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAE4XSUWuDMBSG4f9yrmWlMMbwTspAGC1De1d6kdqjCdVEkuOmlP73ImOrG8nJ9Xfeh4AerkA4EqTQIOXbbPOOEyTQC5KQQj3oipTRbvVYnyR1LSRwUfoM6cvzLVkSO/zilccBD5VYDRYLoc+mC1DLEwaTwklx8hnfSySVOIZaiWMkto5sqJ63SD5Q/RrK543JVdcbSx9vW1//OzKAU03WNnuTCyeztvEx/054rCjJZOVuHYB+Zh7R87+T+7/IYo4hDMDGn2hVPTFv+HMQh1jEAxzv4+VaGa8DAAA=" \ No newline at end of file diff --git a/docs/assets/search.js b/docs/assets/search.js new file mode 100644 index 0000000..e9d4d1d --- /dev/null +++ b/docs/assets/search.js @@ -0,0 +1 @@ +window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAE5WVUY+iMBSF/8t9bhwLiMCbmWziZuNkM272pSEbBiuQgWJoHZ0Q//umoJaalsijnvOdtvde2haa+sQhIi18FmwHke8hYElFIYI84XnyAQiOTQkR7I8sFUXN+EsvzHJRlYAgLRPOKYcI4IIsMTk9W3Jyep4SdBT7wJIkpSlRDReNJUpKz0bxImNr4/GuyrNBX7Qp9t/mqLv2bFhRHepG/P6xMYTdtQlHXJXZn3qd8HxVZuajDh0Tgt+3ol5t37A59KY+G5hRsaXpsaHvCdvVlSH0wTEh+I2e1pvV6y/6bY5V+oTQ0cSJcd28bVavI9PYqxMn0hqp6abQGEHBdvQMUSvDeFEziMCZubMQEOwLWu7k3dOvhyCtq4oyAfFV+0tTUTfS0Vte5oDIHDnubO74cYzIjeiE7o/OhgERbLJhzeYAIo7J5mg2FxBxTTZXs3mAiGeyeZptAYgsTLaFZvMBEd9k8zXbEhBZmmxLzRYAIoHJFmi2EBAJTbZQL6+sNjb2AT80ouuEuRV6L7CsOTZ2A+vtwLLs2NgQ3Hekm7ov2gi6+9lPHyHyW8urJP2U31oL/65jifFt2FvAGKL2clFjKH/J+IwKRk8mej6g53aadxdOc72SFB8qPLTQtzdYQYM1bUveX9zBVgc7HaH6N1FhrsLcEax/lRXmKMyxYP0jdKBaQXzF+RaOF1lSZqLuCiPfIkUvFb200+yhMp6ivDGqStLHmg6OiW3n5EXWcFEnnOEhGyg0sJD97fqw5kJxi3HOsN9BN7GxnTGCQ3GgZcEoRCS+XP4DNn7EuR8KAAA="; \ No newline at end of file diff --git a/docs/assets/style.css b/docs/assets/style.css new file mode 100644 index 0000000..778b949 --- /dev/null +++ b/docs/assets/style.css @@ -0,0 +1,1412 @@ +:root { + /* Light */ + --light-color-background: #f2f4f8; + --light-color-background-secondary: #eff0f1; + --light-color-warning-text: #222; + --light-color-background-warning: #e6e600; + --light-color-icon-background: var(--light-color-background); + --light-color-accent: #c5c7c9; + --light-color-active-menu-item: var(--light-color-accent); + --light-color-text: #222; + --light-color-text-aside: #6e6e6e; + --light-color-link: #1f70c2; + + --light-color-ts-keyword: #056bd6; + --light-color-ts-project: #b111c9; + --light-color-ts-module: var(--light-color-ts-project); + --light-color-ts-namespace: var(--light-color-ts-project); + --light-color-ts-enum: #7e6f15; + --light-color-ts-enum-member: var(--light-color-ts-enum); + --light-color-ts-variable: #4760ec; + --light-color-ts-function: #572be7; + --light-color-ts-class: #1f70c2; + --light-color-ts-interface: #108024; + --light-color-ts-constructor: var(--light-color-ts-class); + --light-color-ts-property: var(--light-color-ts-variable); + --light-color-ts-method: var(--light-color-ts-function); + --light-color-ts-call-signature: var(--light-color-ts-method); + --light-color-ts-index-signature: var(--light-color-ts-property); + --light-color-ts-constructor-signature: var(--light-color-ts-constructor); + --light-color-ts-parameter: var(--light-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --light-color-ts-type-parameter: #a55c0e; + --light-color-ts-accessor: var(--light-color-ts-property); + --light-color-ts-get-signature: var(--light-color-ts-accessor); + --light-color-ts-set-signature: var(--light-color-ts-accessor); + --light-color-ts-type-alias: #d51270; + /* reference not included as links will be colored with the kind that it points to */ + + --light-external-icon: url("data:image/svg+xml;utf8,"); + --light-color-scheme: light; + + /* Dark */ + --dark-color-background: #2b2e33; + --dark-color-background-secondary: #1e2024; + --dark-color-background-warning: #bebe00; + --dark-color-warning-text: #222; + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-accent: #9096a2; + --dark-color-active-menu-item: #5d5d6a; + --dark-color-text: #f5f5f5; + --dark-color-text-aside: #dddddd; + --dark-color-link: #00aff4; + + --dark-color-ts-keyword: #3399ff; + --dark-color-ts-project: #e358ff; + --dark-color-ts-module: var(--dark-color-ts-project); + --dark-color-ts-namespace: var(--dark-color-ts-project); + --dark-color-ts-enum: #f4d93e; + --dark-color-ts-enum-member: var(--dark-color-ts-enum); + --dark-color-ts-variable: #798dff; + --dark-color-ts-function: #a280ff; + --dark-color-ts-class: #8ac4ff; + --dark-color-ts-interface: #6cff87; + --dark-color-ts-constructor: var(--dark-color-ts-class); + --dark-color-ts-property: var(--dark-color-ts-variable); + --dark-color-ts-method: var(--dark-color-ts-function); + --dark-color-ts-call-signature: var(--dark-color-ts-method); + --dark-color-ts-index-signature: var(--dark-color-ts-property); + --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); + --dark-color-ts-parameter: var(--dark-color-ts-variable); + /* type literal not included as links will never be generated to it */ + --dark-color-ts-type-parameter: #e07d13; + --dark-color-ts-accessor: var(--dark-color-ts-property); + --dark-color-ts-get-signature: var(--dark-color-ts-accessor); + --dark-color-ts-set-signature: var(--dark-color-ts-accessor); + --dark-color-ts-type-alias: #ff6492; + /* reference not included as links will be colored with the kind that it points to */ + + --dark-external-icon: url("data:image/svg+xml;utf8,"); + --dark-color-scheme: dark; +} + +@media (prefers-color-scheme: light) { + :root { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + --color-link: var(--light-color-link); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); + } +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + --color-link: var(--dark-color-link); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); + } +} + +html { + color-scheme: var(--color-scheme); +} + +body { + margin: 0; +} + +:root[data-theme="light"] { + --color-background: var(--light-color-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-background-warning: var(--light-color-background-warning); + --color-warning-text: var(--light-color-warning-text); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); + --color-active-menu-item: var(--light-color-active-menu-item); + --color-text: var(--light-color-text); + --color-text-aside: var(--light-color-text-aside); + --color-link: var(--light-color-link); + + --color-ts-keyword: var(--light-color-ts-keyword); + --color-ts-module: var(--light-color-ts-module); + --color-ts-namespace: var(--light-color-ts-namespace); + --color-ts-enum: var(--light-color-ts-enum); + --color-ts-enum-member: var(--light-color-ts-enum-member); + --color-ts-variable: var(--light-color-ts-variable); + --color-ts-function: var(--light-color-ts-function); + --color-ts-class: var(--light-color-ts-class); + --color-ts-interface: var(--light-color-ts-interface); + --color-ts-constructor: var(--light-color-ts-constructor); + --color-ts-property: var(--light-color-ts-property); + --color-ts-method: var(--light-color-ts-method); + --color-ts-call-signature: var(--light-color-ts-call-signature); + --color-ts-index-signature: var(--light-color-ts-index-signature); + --color-ts-constructor-signature: var( + --light-color-ts-constructor-signature + ); + --color-ts-parameter: var(--light-color-ts-parameter); + --color-ts-type-parameter: var(--light-color-ts-type-parameter); + --color-ts-accessor: var(--light-color-ts-accessor); + --color-ts-get-signature: var(--light-color-ts-get-signature); + --color-ts-set-signature: var(--light-color-ts-set-signature); + --color-ts-type-alias: var(--light-color-ts-type-alias); + + --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); +} + +:root[data-theme="dark"] { + --color-background: var(--dark-color-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-background-warning: var(--dark-color-background-warning); + --color-warning-text: var(--dark-color-warning-text); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); + --color-active-menu-item: var(--dark-color-active-menu-item); + --color-text: var(--dark-color-text); + --color-text-aside: var(--dark-color-text-aside); + --color-link: var(--dark-color-link); + + --color-ts-keyword: var(--dark-color-ts-keyword); + --color-ts-module: var(--dark-color-ts-module); + --color-ts-namespace: var(--dark-color-ts-namespace); + --color-ts-enum: var(--dark-color-ts-enum); + --color-ts-enum-member: var(--dark-color-ts-enum-member); + --color-ts-variable: var(--dark-color-ts-variable); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-class: var(--dark-color-ts-class); + --color-ts-interface: var(--dark-color-ts-interface); + --color-ts-constructor: var(--dark-color-ts-constructor); + --color-ts-property: var(--dark-color-ts-property); + --color-ts-method: var(--dark-color-ts-method); + --color-ts-call-signature: var(--dark-color-ts-call-signature); + --color-ts-index-signature: var(--dark-color-ts-index-signature); + --color-ts-constructor-signature: var( + --dark-color-ts-constructor-signature + ); + --color-ts-parameter: var(--dark-color-ts-parameter); + --color-ts-type-parameter: var(--dark-color-ts-type-parameter); + --color-ts-accessor: var(--dark-color-ts-accessor); + --color-ts-get-signature: var(--dark-color-ts-get-signature); + --color-ts-set-signature: var(--dark-color-ts-set-signature); + --color-ts-type-alias: var(--dark-color-ts-type-alias); + + --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); +} + +.always-visible, +.always-visible .tsd-signatures { + display: inherit !important; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + line-height: 1.2; +} + +h1 > a:not(.link), +h2 > a:not(.link), +h3 > a:not(.link), +h4 > a:not(.link), +h5 > a:not(.link), +h6 > a:not(.link) { + text-decoration: none; + color: var(--color-text); +} + +h1 { + font-size: 1.875rem; + margin: 0.67rem 0; +} + +h2 { + font-size: 1.5rem; + margin: 0.83rem 0; +} + +h3 { + font-size: 1.25rem; + margin: 1rem 0; +} + +h4 { + font-size: 1.05rem; + margin: 1.33rem 0; +} + +h5 { + font-size: 1rem; + margin: 1.5rem 0; +} + +h6 { + font-size: 0.875rem; + margin: 2.33rem 0; +} + +.uppercase { + text-transform: uppercase; +} + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +.container { + max-width: 1700px; + padding: 0 2rem; +} + +/* Footer */ +footer { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; + max-height: 3.5rem; +} +.tsd-generator { + margin: 0 1em; +} + +.container-main { + margin: 0 auto; + /* toolbar, footer, margin */ + min-height: calc(100vh - 41px - 56px - 4rem); +} + +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes fade-out { + from { + opacity: 1; + visibility: visible; + } + to { + opacity: 0; + } +} +@keyframes fade-in-delayed { + 0% { + opacity: 0; + } + 33% { + opacity: 0; + } + 100% { + opacity: 1; + } +} +@keyframes fade-out-delayed { + 0% { + opacity: 1; + visibility: visible; + } + 66% { + opacity: 0; + } + 100% { + opacity: 0; + } +} +@keyframes pop-in-from-right { + from { + transform: translate(100%, 0); + } + to { + transform: translate(0, 0); + } +} +@keyframes pop-out-to-right { + from { + transform: translate(0, 0); + visibility: visible; + } + to { + transform: translate(100%, 0); + } +} +body { + background: var(--color-background); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", + Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; + font-size: 16px; + color: var(--color-text); +} + +a { + color: var(--color-link); + text-decoration: none; +} +a:hover { + text-decoration: underline; +} +a.external[target="_blank"] { + background-image: var(--external-icon); + background-position: top 3px right; + background-repeat: no-repeat; + padding-right: 13px; +} + +code, +pre { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 0.2em; + margin: 0; + font-size: 0.875rem; + border-radius: 0.8em; +} + +pre { + position: relative; + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; + padding: 10px; + border: 1px solid var(--color-accent); +} +pre code { + padding: 0; + font-size: 100%; +} +pre > button { + position: absolute; + top: 10px; + right: 10px; + opacity: 0; + transition: opacity 0.1s; + box-sizing: border-box; +} +pre:hover > button, +pre > button.visible { + opacity: 1; +} + +blockquote { + margin: 1em 0; + padding-left: 1em; + border-left: 4px solid gray; +} + +.tsd-typography { + line-height: 1.333em; +} +.tsd-typography ul { + list-style: square; + padding: 0 0 0 20px; + margin: 0; +} +.tsd-typography .tsd-index-panel h3, +.tsd-index-panel .tsd-typography h3, +.tsd-typography h4, +.tsd-typography h5, +.tsd-typography h6 { + font-size: 1em; +} +.tsd-typography h5, +.tsd-typography h6 { + font-weight: normal; +} +.tsd-typography p, +.tsd-typography ul, +.tsd-typography ol { + margin: 1em 0; +} +.tsd-typography table { + border-collapse: collapse; + border: none; +} +.tsd-typography td, +.tsd-typography th { + padding: 6px 13px; + border: 1px solid var(--color-accent); +} +.tsd-typography thead, +.tsd-typography tr:nth-child(even) { + background-color: var(--color-background-secondary); +} + +.tsd-breadcrumb { + margin: 0; + padding: 0; + color: var(--color-text-aside); +} +.tsd-breadcrumb a { + color: var(--color-text-aside); + text-decoration: none; +} +.tsd-breadcrumb a:hover { + text-decoration: underline; +} +.tsd-breadcrumb li { + display: inline; +} +.tsd-breadcrumb li:after { + content: " / "; +} + +.tsd-comment-tags { + display: flex; + flex-direction: column; +} +dl.tsd-comment-tag-group { + display: flex; + align-items: center; + overflow: hidden; + margin: 0.5em 0; +} +dl.tsd-comment-tag-group dt { + display: flex; + margin-right: 0.5em; + font-size: 0.875em; + font-weight: normal; +} +dl.tsd-comment-tag-group dd { + margin: 0; +} +code.tsd-tag { + padding: 0.25em 0.4em; + border: 0.1em solid var(--color-accent); + margin-right: 0.25em; + font-size: 70%; +} +h1 code.tsd-tag:first-of-type { + margin-left: 0.25em; +} + +dl.tsd-comment-tag-group dd:before, +dl.tsd-comment-tag-group dd:after { + content: " "; +} +dl.tsd-comment-tag-group dd pre, +dl.tsd-comment-tag-group dd:after { + clear: both; +} +dl.tsd-comment-tag-group p { + margin: 0; +} + +.tsd-panel.tsd-comment .lead { + font-size: 1.1em; + line-height: 1.333em; + margin-bottom: 2em; +} +.tsd-panel.tsd-comment .lead:last-child { + margin-bottom: 0; +} + +.tsd-filter-visibility h4 { + font-size: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.5rem; + margin: 0; +} +.tsd-filter-item:not(:last-child) { + margin-bottom: 0.5rem; +} +.tsd-filter-input { + display: flex; + width: fit-content; + width: -moz-fit-content; + align-items: center; + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + cursor: pointer; +} +.tsd-filter-input input[type="checkbox"] { + cursor: pointer; + position: absolute; + width: 1.5em; + height: 1.5em; + opacity: 0; +} +.tsd-filter-input input[type="checkbox"]:disabled { + pointer-events: none; +} +.tsd-filter-input svg { + cursor: pointer; + width: 1.5em; + height: 1.5em; + margin-right: 0.5em; + border-radius: 0.33em; + /* Leaving this at full opacity breaks event listeners on Firefox. + Don't remove unless you know what you're doing. */ + opacity: 0.99; +} +.tsd-filter-input input[type="checkbox"]:focus + svg { + transform: scale(0.95); +} +.tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { + transform: scale(1); +} +.tsd-checkbox-background { + fill: var(--color-accent); +} +input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { + stroke: var(--color-text); +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { + fill: var(--color-background); + stroke: var(--color-accent); + stroke-width: 0.25rem; +} +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { + stroke: var(--color-accent); +} + +.tsd-theme-toggle { + padding-top: 0.75rem; +} +.tsd-theme-toggle > h4 { + display: inline; + vertical-align: middle; + margin-right: 0.75rem; +} + +.tsd-hierarchy { + list-style: square; + margin: 0; +} +.tsd-hierarchy .target { + font-weight: bold; +} + +.tsd-full-hierarchy:not(:last-child) { + margin-bottom: 1em; + padding-bottom: 1em; + border-bottom: 1px solid var(--color-accent); +} +.tsd-full-hierarchy, +.tsd-full-hierarchy ul { + list-style: none; + margin: 0; + padding: 0; +} +.tsd-full-hierarchy ul { + padding-left: 1.5rem; +} +.tsd-full-hierarchy a { + padding: 0.25rem 0 !important; + font-size: 1rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} + +.tsd-panel-group.tsd-index-group { + margin-bottom: 0; +} +.tsd-index-panel .tsd-index-list { + list-style: none; + line-height: 1.333em; + margin: 0; + padding: 0.25rem 0 0 0; + overflow: hidden; + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 1rem; + grid-template-rows: auto; +} +@media (max-width: 1024px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(2, 1fr); + } +} +@media (max-width: 768px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(1, 1fr); + } +} +.tsd-index-panel .tsd-index-list li { + -webkit-page-break-inside: avoid; + -moz-page-break-inside: avoid; + -ms-page-break-inside: avoid; + -o-page-break-inside: avoid; + page-break-inside: avoid; +} + +.tsd-flag { + display: inline-block; + padding: 0.25em 0.4em; + border-radius: 4px; + color: var(--color-comment-tag-text); + background-color: var(--color-comment-tag); + text-indent: 0; + font-size: 75%; + line-height: 1; + font-weight: normal; +} + +.tsd-anchor { + position: relative; + top: -100px; +} + +.tsd-member { + position: relative; +} +.tsd-member .tsd-anchor + h3 { + display: flex; + align-items: center; + margin-top: 0; + margin-bottom: 0; + border-bottom: none; +} + +.tsd-navigation.settings { + margin: 1rem 0; +} +.tsd-navigation > a, +.tsd-navigation .tsd-accordion-summary { + width: calc(100% - 0.25rem); + display: flex; + align-items: center; +} +.tsd-navigation a, +.tsd-navigation summary > span, +.tsd-page-navigation a { + display: flex; + width: calc(100% - 0.25rem); + align-items: center; + padding: 0.25rem; + color: var(--color-text); + text-decoration: none; + box-sizing: border-box; +} +.tsd-navigation a.current, +.tsd-page-navigation a.current { + background: var(--color-active-menu-item); +} +.tsd-navigation a:hover, +.tsd-page-navigation a:hover { + text-decoration: underline; +} +.tsd-navigation ul, +.tsd-page-navigation ul { + margin-top: 0; + margin-bottom: 0; + padding: 0; + list-style: none; +} +.tsd-navigation li, +.tsd-page-navigation li { + padding: 0; + max-width: 100%; +} +.tsd-nested-navigation { + margin-left: 3rem; +} +.tsd-nested-navigation > li > details { + margin-left: -1.5rem; +} +.tsd-small-nested-navigation { + margin-left: 1.5rem; +} +.tsd-small-nested-navigation > li > details { + margin-left: -1.5rem; +} + +.tsd-page-navigation ul { + padding-left: 1.75rem; +} + +#tsd-sidebar-links a { + margin-top: 0; + margin-bottom: 0.5rem; + line-height: 1.25rem; +} +#tsd-sidebar-links a:last-of-type { + margin-bottom: 0; +} + +a.tsd-index-link { + padding: 0.25rem 0 !important; + font-size: 1rem; + line-height: 1.25rem; + display: inline-flex; + align-items: center; + color: var(--color-text); +} +.tsd-accordion-summary { + list-style-type: none; /* hide marker on non-safari */ + outline: none; /* broken on safari, so just hide it */ +} +.tsd-accordion-summary::-webkit-details-marker { + display: none; /* hide marker on safari */ +} +.tsd-accordion-summary, +.tsd-accordion-summary a { + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + + cursor: pointer; +} +.tsd-accordion-summary a { + width: calc(100% - 1.5rem); +} +.tsd-accordion-summary > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; +} +.tsd-index-accordion .tsd-accordion-summary > svg { + margin-left: 0.25rem; +} +.tsd-index-content > :not(:first-child) { + margin-top: 0.75rem; +} +.tsd-index-heading { + margin-top: 1.5rem; + margin-bottom: 0.75rem; +} + +.tsd-kind-icon { + margin-right: 0.5rem; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; +} +.tsd-kind-icon path { + transform-origin: center; + transform: scale(1.1); +} +.tsd-signature > .tsd-kind-icon { + margin-right: 0.8rem; +} + +.tsd-panel { + margin-bottom: 2.5rem; +} +.tsd-panel.tsd-member { + margin-bottom: 4rem; +} +.tsd-panel:empty { + display: none; +} +.tsd-panel > h1, +.tsd-panel > h2, +.tsd-panel > h3 { + margin: 1.5rem -1.5rem 0.75rem -1.5rem; + padding: 0 1.5rem 0.75rem 1.5rem; +} +.tsd-panel > h1.tsd-before-signature, +.tsd-panel > h2.tsd-before-signature, +.tsd-panel > h3.tsd-before-signature { + margin-bottom: 0; + border-bottom: none; +} + +.tsd-panel-group { + margin: 4rem 0; +} +.tsd-panel-group.tsd-index-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group details { + margin: 2rem 0; +} + +#tsd-search { + transition: background-color 0.2s; +} +#tsd-search .title { + position: relative; + z-index: 2; +} +#tsd-search .field { + position: absolute; + left: 0; + top: 0; + right: 2.5rem; + height: 100%; +} +#tsd-search .field input { + box-sizing: border-box; + position: relative; + top: -50px; + z-index: 1; + width: 100%; + padding: 0 10px; + opacity: 0; + outline: 0; + border: 0; + background: transparent; + color: var(--color-text); +} +#tsd-search .field label { + position: absolute; + overflow: hidden; + right: -40px; +} +#tsd-search .field input, +#tsd-search .title, +#tsd-toolbar-links a { + transition: opacity 0.2s; +} +#tsd-search .results { + position: absolute; + visibility: hidden; + top: 40px; + width: 100%; + margin: 0; + padding: 0; + list-style: none; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); +} +#tsd-search .results li { + background-color: var(--color-background); + line-height: initial; + padding: 4px; +} +#tsd-search .results li:nth-child(even) { + background-color: var(--color-background-secondary); +} +#tsd-search .results li.state { + display: none; +} +#tsd-search .results li.current:not(.no-results), +#tsd-search .results li:hover:not(.no-results) { + background-color: var(--color-accent); +} +#tsd-search .results a { + display: flex; + align-items: center; + padding: 0.25rem; + box-sizing: border-box; +} +#tsd-search .results a:before { + top: 10px; +} +#tsd-search .results span.parent { + color: var(--color-text-aside); + font-weight: normal; +} +#tsd-search.has-focus { + background-color: var(--color-accent); +} +#tsd-search.has-focus .field input { + top: 0; + opacity: 1; +} +#tsd-search.has-focus .title, +#tsd-search.has-focus #tsd-toolbar-links a { + z-index: 0; + opacity: 0; +} +#tsd-search.has-focus .results { + visibility: visible; +} +#tsd-search.loading .results li.state.loading { + display: block; +} +#tsd-search.failure .results li.state.failure { + display: block; +} + +#tsd-toolbar-links { + position: absolute; + top: 0; + right: 2rem; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-end; +} +#tsd-toolbar-links a { + margin-left: 1.5rem; +} +#tsd-toolbar-links a:hover { + text-decoration: underline; +} + +.tsd-signature { + margin: 0 0 1rem 0; + padding: 1rem 0.5rem; + border: 1px solid var(--color-accent); + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-size: 14px; + overflow-x: auto; +} + +.tsd-signature-keyword { + color: var(--color-ts-keyword); + font-weight: normal; +} + +.tsd-signature-symbol { + color: var(--color-text-aside); + font-weight: normal; +} + +.tsd-signature-type { + font-style: italic; + font-weight: normal; +} + +.tsd-signatures { + padding: 0; + margin: 0 0 1em 0; + list-style-type: none; +} +.tsd-signatures .tsd-signature { + margin: 0; + border-color: var(--color-accent); + border-width: 1px 0; + transition: background-color 0.1s; +} +.tsd-description .tsd-signatures .tsd-signature { + border-width: 1px; +} + +ul.tsd-parameter-list, +ul.tsd-type-parameter-list { + list-style: square; + margin: 0; + padding-left: 20px; +} +ul.tsd-parameter-list > li.tsd-parameter-signature, +ul.tsd-type-parameter-list > li.tsd-parameter-signature { + list-style: none; + margin-left: -20px; +} +ul.tsd-parameter-list h5, +ul.tsd-type-parameter-list h5 { + font-size: 16px; + margin: 1em 0 0.5em 0; +} +.tsd-sources { + margin-top: 1rem; + font-size: 0.875em; +} +.tsd-sources a { + color: var(--color-text-aside); + text-decoration: underline; +} +.tsd-sources ul { + list-style: none; + padding: 0; +} + +.tsd-page-toolbar { + position: sticky; + z-index: 1; + top: 0; + left: 0; + width: 100%; + color: var(--color-text); + background: var(--color-background-secondary); + border-bottom: 1px var(--color-accent) solid; + transition: transform 0.3s ease-in-out; +} +.tsd-page-toolbar a { + color: var(--color-text); + text-decoration: none; +} +.tsd-page-toolbar a.title { + font-weight: bold; +} +.tsd-page-toolbar a.title:hover { + text-decoration: underline; +} +.tsd-page-toolbar .tsd-toolbar-contents { + display: flex; + justify-content: space-between; + height: 2.5rem; + margin: 0 auto; +} +.tsd-page-toolbar .table-cell { + position: relative; + white-space: nowrap; + line-height: 40px; +} +.tsd-page-toolbar .table-cell:first-child { + width: 100%; +} +.tsd-page-toolbar .tsd-toolbar-icon { + box-sizing: border-box; + line-height: 0; + padding: 12px 0; +} + +.tsd-widget { + display: inline-block; + overflow: hidden; + opacity: 0.8; + height: 40px; + transition: + opacity 0.1s, + background-color 0.2s; + vertical-align: bottom; + cursor: pointer; +} +.tsd-widget:hover { + opacity: 0.9; +} +.tsd-widget.active { + opacity: 1; + background-color: var(--color-accent); +} +.tsd-widget.no-caption { + width: 40px; +} +.tsd-widget.no-caption:before { + margin: 0; +} + +.tsd-widget.options, +.tsd-widget.menu { + display: none; +} +input[type="checkbox"] + .tsd-widget:before { + background-position: -120px 0; +} +input[type="checkbox"]:checked + .tsd-widget:before { + background-position: -160px 0; +} + +img { + max-width: 100%; +} + +.tsd-anchor-icon { + display: inline-flex; + align-items: center; + margin-left: 0.5rem; + vertical-align: middle; + color: var(--color-text); +} + +.tsd-anchor-icon svg { + width: 1em; + height: 1em; + visibility: hidden; +} + +.tsd-anchor-link:hover > .tsd-anchor-icon svg { + visibility: visible; +} + +.deprecated { + text-decoration: line-through !important; +} + +.warning { + padding: 1rem; + color: var(--color-warning-text); + background: var(--color-background-warning); +} + +.tsd-kind-project { + color: var(--color-ts-project); +} +.tsd-kind-module { + color: var(--color-ts-module); +} +.tsd-kind-namespace { + color: var(--color-ts-namespace); +} +.tsd-kind-enum { + color: var(--color-ts-enum); +} +.tsd-kind-enum-member { + color: var(--color-ts-enum-member); +} +.tsd-kind-variable { + color: var(--color-ts-variable); +} +.tsd-kind-function { + color: var(--color-ts-function); +} +.tsd-kind-class { + color: var(--color-ts-class); +} +.tsd-kind-interface { + color: var(--color-ts-interface); +} +.tsd-kind-constructor { + color: var(--color-ts-constructor); +} +.tsd-kind-property { + color: var(--color-ts-property); +} +.tsd-kind-method { + color: var(--color-ts-method); +} +.tsd-kind-call-signature { + color: var(--color-ts-call-signature); +} +.tsd-kind-index-signature { + color: var(--color-ts-index-signature); +} +.tsd-kind-constructor-signature { + color: var(--color-ts-constructor-signature); +} +.tsd-kind-parameter { + color: var(--color-ts-parameter); +} +.tsd-kind-type-literal { + color: var(--color-ts-type-literal); +} +.tsd-kind-type-parameter { + color: var(--color-ts-type-parameter); +} +.tsd-kind-accessor { + color: var(--color-ts-accessor); +} +.tsd-kind-get-signature { + color: var(--color-ts-get-signature); +} +.tsd-kind-set-signature { + color: var(--color-ts-set-signature); +} +.tsd-kind-type-alias { + color: var(--color-ts-type-alias); +} + +/* if we have a kind icon, don't color the text by kind */ +.tsd-kind-icon ~ span { + color: var(--color-text); +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--color-accent) var(--color-icon-background); +} + +*::-webkit-scrollbar { + width: 0.75rem; +} + +*::-webkit-scrollbar-track { + background: var(--color-icon-background); +} + +*::-webkit-scrollbar-thumb { + background-color: var(--color-accent); + border-radius: 999rem; + border: 0.25rem solid var(--color-icon-background); +} + +/* mobile */ +@media (max-width: 769px) { + .tsd-widget.options, + .tsd-widget.menu { + display: inline-block; + } + + .container-main { + display: flex; + } + html .col-content { + float: none; + max-width: 100%; + width: 100%; + } + html .col-sidebar { + position: fixed !important; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + z-index: 1024; + top: 0 !important; + bottom: 0 !important; + left: auto !important; + right: 0 !important; + padding: 1.5rem 1.5rem 0 0; + width: 75vw; + visibility: hidden; + background-color: var(--color-background); + transform: translate(100%, 0); + } + html .col-sidebar > *:last-child { + padding-bottom: 20px; + } + html .overlay { + content: ""; + display: block; + position: fixed; + z-index: 1023; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.75); + visibility: hidden; + } + + .to-has-menu .overlay { + animation: fade-in 0.4s; + } + + .to-has-menu .col-sidebar { + animation: pop-in-from-right 0.4s; + } + + .from-has-menu .overlay { + animation: fade-out 0.4s; + } + + .from-has-menu .col-sidebar { + animation: pop-out-to-right 0.4s; + } + + .has-menu body { + overflow: hidden; + } + .has-menu .overlay { + visibility: visible; + } + .has-menu .col-sidebar { + visibility: visible; + transform: translate(0, 0); + display: flex; + flex-direction: column; + gap: 1.5rem; + max-height: 100vh; + padding: 1rem 2rem; + } + .has-menu .tsd-navigation { + max-height: 100%; + } +} + +/* one sidebar */ +@media (min-width: 770px) { + .container-main { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + grid-template-areas: "sidebar content"; + margin: 2rem auto; + } + + .col-sidebar { + grid-area: sidebar; + } + .col-content { + grid-area: content; + padding: 0 1rem; + } +} +@media (min-width: 770px) and (max-width: 1399px) { + .col-sidebar { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + padding-top: 1rem; + } + .site-menu { + margin-top: 1rem; + } +} + +/* two sidebars */ +@media (min-width: 1200px) { + .container-main { + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); + grid-template-areas: "sidebar content toc"; + } + + .col-sidebar { + display: contents; + } + + .page-menu { + grid-area: toc; + padding-left: 1rem; + } + .site-menu { + grid-area: sidebar; + } + + .site-menu { + margin-top: 1rem 0; + } + + .page-menu, + .site-menu { + max-height: calc(100vh - 2rem - 42px); + overflow: auto; + position: sticky; + top: 42px; + } +} diff --git a/docs/functions/getHMACKey.html b/docs/functions/getHMACKey.html new file mode 100644 index 0000000..12fdfe0 --- /dev/null +++ b/docs/functions/getHMACKey.html @@ -0,0 +1,10 @@ +getHMACKey | typepki-webcrypto - v0.1.0

Function getHMACKey

  • get HMAC key object

    +

    Parameters

    • alg: string

      HMAC algorithm name ("hmacSHA{1,256,384,512}")

      +
    • hKey: string

      hexadecimal string of HMAC key

      +

    Returns Promise<CryptoKey>

    HMAC key object

    +

    Description

    This function generates CryptoKey object with specified +HMAC algorithm and a hexadecimal string of HMAC key value.

    +

    See

    getNewHMACKey

    +

    Example

    await getHMACKey("hmacSHA256", "3b6839...") -> CryptoKey object
    +
    +
\ No newline at end of file diff --git a/docs/functions/getNewHMACKey.html b/docs/functions/getNewHMACKey.html new file mode 100644 index 0000000..cf12c70 --- /dev/null +++ b/docs/functions/getNewHMACKey.html @@ -0,0 +1,14 @@ +getNewHMACKey | typepki-webcrypto - v0.1.0

Function getNewHMACKey

  • generate new HMAC key with specified HMAC algorithm

    +

    Parameters

    • alg: string

      HMAC algorithm ("hmacSHA{1,256,384,512}")

      +

    Returns string

    hexadecimal string of HMAC key

    +

    Description

    This function generates a HMAC key with specified HMAC +algorithm with crypto.getRandomValues not +crypto.subtle.generateKey. Its byte length will be +the same as generateKey as following:

    +
      +
    • hmacSHA1, hmacSHA256: 64 bytes
    • +
    • hmacSHA384, hmacSHA512: 128 bytes
    • +
    +

    Example

    getNewHMACKey("hmacSHA256") -> "8ab134..." (64 bytes)
    getNewHMACKey("hmacSHA512") -> "374cdf..." (128 bytes) +
    +
\ No newline at end of file diff --git a/docs/functions/getSecureRandom.html b/docs/functions/getSecureRandom.html new file mode 100644 index 0000000..d72d283 --- /dev/null +++ b/docs/functions/getSecureRandom.html @@ -0,0 +1,9 @@ +getSecureRandom | typepki-webcrypto - v0.1.0

Function getSecureRandom

  • generate a secure random hexadecimal string

    +

    Parameters

    • nbyte: number

      length of random bytes

      +

    Returns string

    hexadecimal string of generated random bytes

    +

    Description

    This function generates a secure random hexadecimal string +with specified bytes by crypto.getRandomValues() +which uses a pseudo-random number generator(PRNG) algorithm.

    +

    Example

    getSecureRandom(3) -> "f73ad5"
    getSecureRandom(3) -> "d431c6"
    getSecureRandom(256) -> "147ac8..." (string length will be 512=256*2) +
    +
\ No newline at end of file diff --git a/docs/functions/hashab.html b/docs/functions/hashab.html new file mode 100644 index 0000000..d4d890b --- /dev/null +++ b/docs/functions/hashab.html @@ -0,0 +1,7 @@ +hashab | typepki-webcrypto - v0.1.0
  • get hexadecimal hash value of ArrayBuffer with specified hash algorithm

    +

    Parameters

    • alg: string

      hash algorithm (ex. "SHA-256")

      +
    • ab: ArrayBuffer

      ArrayBuffer value to be hashed

      +

    Returns Promise<string>

    hexadecimal hash value

    +

    Example

    await hashab("SHA-256", hextoArrayBuffer("616161")
    -> ... +
    +
\ No newline at end of file diff --git a/docs/functions/hashhex.html b/docs/functions/hashhex.html new file mode 100644 index 0000000..c0c598d --- /dev/null +++ b/docs/functions/hashhex.html @@ -0,0 +1,7 @@ +hashhex | typepki-webcrypto - v0.1.0

Function hashhex

  • get hexadecimal hash value of hexadecimal string data with specified hash algorithm

    +

    Parameters

    • alg: string

      hash algorithm (ex. "SHA-256")

      +
    • hex: string

      hexadecimal string value to be hashed

      +

    Returns Promise<string>

    hexadecimal hash value

    +

    Example

    await hashhex("SHA-256", "616161")
    -> ... +
    +
\ No newline at end of file diff --git a/docs/functions/hashrstr.html b/docs/functions/hashrstr.html new file mode 100644 index 0000000..e683237 --- /dev/null +++ b/docs/functions/hashrstr.html @@ -0,0 +1,7 @@ +hashrstr | typepki-webcrypto - v0.1.0

Function hashrstr

  • get hexadecimal hash value of raw string with specified hash algorithm

    +

    Parameters

    • alg: string

      hash algorithm (ex. "SHA-256")

      +
    • rstr: string

      hexadecimal string value to be hashed

      +

    Returns Promise<string>

    hexadecimal hash value

    +

    Example

    await hashrstr("SHA-256", "\0\0\0")
    -> ... +
    +
\ No newline at end of file diff --git a/docs/functions/hashutf8.html b/docs/functions/hashutf8.html new file mode 100644 index 0000000..a207e68 --- /dev/null +++ b/docs/functions/hashutf8.html @@ -0,0 +1,7 @@ +hashutf8 | typepki-webcrypto - v0.1.0

Function hashutf8

  • get hexadecimal hash value of UTF-8 string with specified hash algorithm

    +

    Parameters

    • alg: string

      hash algorithm (ex. "SHA-256")

      +
    • u8str: string

      hexadecimal string value to be hashed

      +

    Returns Promise<string>

    hexadecimal hash value

    +

    Example

    await hashutf8("SHA-256", "そらSky")
    -> ... +
    +
\ No newline at end of file diff --git a/docs/functions/importPEM.html b/docs/functions/importPEM.html new file mode 100644 index 0000000..225e348 --- /dev/null +++ b/docs/functions/importPEM.html @@ -0,0 +1,9 @@ +importPEM | typepki-webcrypto - v0.1.0

Function importPEM

  • import key from PEM private/public key string

    +

    Parameters

    • pem: string

      PEM PKCS#8 private key or public key string

      +
    • alg: string

      signature algorithm (SHA{1,224,256,384,512}with{RSA,RSAandMGF1,ECDSA})

      +
    • Optional sigopt: string | number

    Returns Promise<CryptoKey>

    CryptoKey object of W3C Web Crypto API

    +

    See

    https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey

    +

    Description

    This function import a CryptoKey object from PEM key file.

    +

    Example

    let key = await importPEM("-----BEGIN PRIVATE...", "SHA256withRSA");
    +
    +
\ No newline at end of file diff --git a/docs/functions/sigAlgToHashAlg.html b/docs/functions/sigAlgToHashAlg.html new file mode 100644 index 0000000..e814946 --- /dev/null +++ b/docs/functions/sigAlgToHashAlg.html @@ -0,0 +1 @@ +sigAlgToHashAlg | typepki-webcrypto - v0.1.0

Function sigAlgToHashAlg

  • Parameters

    • alg: string

    Returns string | null

\ No newline at end of file diff --git a/docs/functions/sigRStoASN1.html b/docs/functions/sigRStoASN1.html new file mode 100644 index 0000000..024910a --- /dev/null +++ b/docs/functions/sigRStoASN1.html @@ -0,0 +1,13 @@ +sigRStoASN1 | typepki-webcrypto - v0.1.0

Function sigRStoASN1

  • convert ECDSA signature value from RS concatinated to ASN.1 encoded

    +

    Parameters

    • hRS: string

      hexadecimal string of R and S concatinated signature value

      +

    Returns string

    ASN.1 DER encoded ECDSA signature value

    +

    Description

    ECDSA signature value has two types of encoding:

    +
      +
    • R and S value concatinated encoding used in W3C Web Crypto API or JSON Web Signature.
    • +
    • ASN.1 SEQUENCE of INTEGER R and S value used in OpenSSL
    • +
    +

    This function convert a ECDSA signature encoding from +concatinated to ASN.1. This function supports ECDSA signatures by P-256, P-384 and P-521.

    +

    Example

    sigRStoASN1("
    69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060
    76ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f")
    ->
    "3044
    0220
    69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060
    0220
    76ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f" +
    +
\ No newline at end of file diff --git a/docs/functions/signHMACHex.html b/docs/functions/signHMACHex.html new file mode 100644 index 0000000..8ffbed9 --- /dev/null +++ b/docs/functions/signHMACHex.html @@ -0,0 +1,9 @@ +signHMACHex | typepki-webcrypto - v0.1.0

Function signHMACHex

  • sign hexadecimal data with HMAC

    +

    Parameters

    • alg: string

      HMAC algorithm name ("hmacSHA{1,256,384,512}")

      +
    • key: string | CryptoKey

      CryptoKey object or hexadecimal string of HMAC key

      +
    • hData: string

      hexadecimal string data to be signed

      +

    Returns Promise<string>

    hexadecimal string of HMAC signature

    +

    See

    verifyHMACHex

    +

    Example

    await signHMAXHex("hmacSHA256", "9abf1245...", "616161") -> "7c8ffa..."
    +
    +
\ No newline at end of file diff --git a/docs/functions/signHex.html b/docs/functions/signHex.html new file mode 100644 index 0000000..aa81367 --- /dev/null +++ b/docs/functions/signHex.html @@ -0,0 +1,9 @@ +signHex | typepki-webcrypto - v0.1.0

Function signHex

  • sign hexadecimal data with specified private key and algorithm

    +

    Parameters

    • alg: string

      signature algorithm name (ex. SHA256withRSA)

      +
    • key: CryptoKey

      private key object

      +
    • hData: string

      hexadecimal data to be signed

      +

    Returns Promise<string>

    hexadecimal signature value

    +

    See

    https://developer.mozilla.org/ja/docs/Web/API/SubtleCrypto/sign

    +

    Example

    await signHex("SHA256withECDSA", prvkey, "616161") -> "631b3f..."
    +
    +
\ No newline at end of file diff --git a/docs/functions/verifyHMACHex.html b/docs/functions/verifyHMACHex.html new file mode 100644 index 0000000..379e994 --- /dev/null +++ b/docs/functions/verifyHMACHex.html @@ -0,0 +1,10 @@ +verifyHMACHex | typepki-webcrypto - v0.1.0

Function verifyHMACHex

  • verify HMAC signature

    +

    Parameters

    • alg: string

      HMAC algorithm name ("hmacSHA{1,256,384,512}")

      +
    • key: string | CryptoKey

      CryptoKey object or hexadecimal string of HMAC key

      +
    • hSig: string

      hexadecimal string of HMAC signature value

      +
    • hData: string

      hexadecimal string of data to be verified

      +

    Returns Promise<boolean>

    true if the signature is valid

    +

    See

    signHMACHex

    +

    Example

    await verifyHMACHex("hmacSHA256", "9abf1245...", "7ff2bc...", "616161") -> true
    +
    +
\ No newline at end of file diff --git a/docs/functions/verifyHex.html b/docs/functions/verifyHex.html new file mode 100644 index 0000000..06ad0c1 --- /dev/null +++ b/docs/functions/verifyHex.html @@ -0,0 +1,11 @@ +verifyHex | typepki-webcrypto - v0.1.0

Function verifyHex

  • verify signature with specified public key, algorithm and data

    +

    Parameters

    • alg: string

      signature algorithm name (ex. SHA256withRSA)

      +
    • key: CryptoKey

      public key object

      +
    • hSig: string

      hexadecimal signature value

      +
    • hData: string

      hexadecimal data to be verified

      +
    • Optional sigopt: string | number

      salt length for RSA-PSS or curve name for ECDSA

      +

    Returns Promise<boolean>

    true if signature is valid

    +

    See

    https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify

    +

    Example

    await verifyHex("SHA256withECDSA", pubkey, "91ac...", "616161") -> true
    +
    +
\ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 06e5d21..608ee59 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,5 +1,12 @@ - - -

typepki-wegbcrypto

- - +typepki-webcrypto - v0.1.0

typepki-webcrypto - v0.1.0

typepki-webcrypto: W3C Web Crypto API helper function sub module for TypePKI library

The 'TypePKI' library is an opensource free TypeScript PKI library which is the successor of the long lived jsrsasign library.

+

The 'typepki-webcrypto' is W3C Web Crypto API [1][2] helper function sub module for TypePKI library.

+

FEATURE

    +
  • easy use for
      +
    • keypair generation
    • +
    • key import
    • +
    • key export
    • +
    +
  • +
  • Dual CommonJS/ES module package supporting CommonJS(CJS) and ES modules
  • +
+
\ No newline at end of file diff --git a/docs/modules.html b/docs/modules.html new file mode 100644 index 0000000..f1c7540 --- /dev/null +++ b/docs/modules.html @@ -0,0 +1,15 @@ +typepki-webcrypto - v0.1.0
\ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..915acc5 --- /dev/null +++ b/package.json @@ -0,0 +1,77 @@ +{ + "name": "typepki-webcrypto", + "version": "0.1.0", + "author": "Kenji Urushima ", + "description": "W3C Web Crypto API helper function sub module for TypePKI library (beta)", + "homepage": "https://kjur.github.io/typepki-webcrypto", + "repository": { + "type": "git", + "url": "https://github.com/kjur/typepki-webcrypto.git" + }, + "bugs": { + "url": "https://github.com/kjur/typepki-webcrypto/issues" + }, + "keywords": [ + "cryptography", + "webcryptoapi", + "publickey", + "hash", + "kdf", + "hmac" + ], + "license": "MIT", + "scripts": { + "deploy": "", + "build": "run-z build:transpile,build:esm,build:cjs", + "build:transpile": "bun build.mts", + "build:esm": "tsc --project tsconfig.build.esm.json", + "build:cjs": "tsc --project tsconfig.build.cjs.json", + "check": "run-z check:type,check:static", + "check:type": "tsc --noEmit", + "check:static": "biome check .", + "fix": "$npm_execpath run check:static --apply-unsafe", + "test": "bun test", + "precommit": "run-z check:type fix test build", + "prepublish": "attw --pack .", + "run-z": "run-z", + "doc": "typedoc --includeVersion --cleanOutputDir false --tsconfig ./tsconfig.typedoc.json --options ./typedoc.json src/index.mts" + }, + "files": [ + "src", + "dist", + "package.json", + "tsconfig.json", + "LICENSE" + ], + "exports": { + ".": { + "import": { + "types": "./dist/import/index.d.mts", + "default": "./dist/import/index.mjs" + }, + "require": { + "types": "./dist/require/index.d.cts", + "default": "./dist/require/index.cjs" + } + } + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.15.0", + "@biomejs/biome": "1.5.3", + "@changesets/cli": "^2.27.1", + "@tsconfig/node17": "^17.1.4", + "@types/bun": "^1.1.1", + "@types/node": "^17.0.45", + "bun-types": "^1.1.4", + "esbuild": "^0.20.0", + "jest": "^29.7.0", + "run-z": "^2.0.0", + "typedoc": "^0.25.13", + "typepki-strconv": "^0.3.0", + "typescript": "^5.4.5" + }, + "dependencies": { + "typepki-asn1gen": "^0.1.0", + "typepki-webcrypto": "file:typepki-webcrypto-0.1.0.tgz" + } +} diff --git a/src/index.cts b/src/index.cts new file mode 100644 index 0000000..a376b54 --- /dev/null +++ b/src/index.cts @@ -0,0 +1 @@ +module.exports = require("./index.mts"); diff --git a/src/index.mts b/src/index.mts new file mode 100644 index 0000000..f2a24db --- /dev/null +++ b/src/index.mts @@ -0,0 +1,384 @@ +import { hextoBA, rstrtohex, utf8tohex, ArrayBuffertohex, hextoArrayBuffer, pemtohex, ishex } from "typepki-strconv"; +import { pospad, getASN1 } from "typepki-asn1gen"; + + +// == hash =========================== +/** + * get hexadecimal hash value of ArrayBuffer with specified hash algorithm + * @param alg - hash algorithm (ex. "SHA-256") + * @param ab - ArrayBuffer value to be hashed + * @return hexadecimal hash value + * @example + * await hashab("SHA-256", hextoArrayBuffer("616161") + * -> ... + */ +export async function hashab(alg: string, ab: ArrayBuffer): Promise { + return ArrayBuffertohex(await crypto.subtle.digest({name: alg}, ab)); +} + +/** + * get hexadecimal hash value of hexadecimal string data with specified hash algorithm + * @param alg - hash algorithm (ex. "SHA-256") + * @param hex - hexadecimal string value to be hashed + * @return hexadecimal hash value + * @example + * await hashhex("SHA-256", "616161") + * -> ... + */ +export async function hashhex(alg: string, hex: string): Promise { + return await hashab(alg, hextoArrayBuffer(hex)); +} + +/** + * get hexadecimal hash value of UTF-8 string with specified hash algorithm + * @param alg - hash algorithm (ex. "SHA-256") + * @param u8str - hexadecimal string value to be hashed + * @return hexadecimal hash value + * @example + * await hashutf8("SHA-256", "そらSky") + * -> ... + */ +export async function hashutf8(alg: string, u8str: string): Promise { + return await hashhex(alg, utf8tohex(u8str)); +} + +/** + * get hexadecimal hash value of raw string with specified hash algorithm + * @param alg - hash algorithm (ex. "SHA-256") + * @param rstr - hexadecimal string value to be hashed + * @return hexadecimal hash value + * @example + * await hashrstr("SHA-256", "\0\0\0") + * -> ... + */ +export async function hashrstr(alg: string, rstr: string): Promise { + return await hashhex(alg, rstrtohex(rstr)); +} + +/** + * sign hexadecimal data with specified private key and algorithm + * @param alg - signature algorithm name (ex. SHA256withRSA) + * @param key - private key object + * @param hData - hexadecimal data to be signed + * @return hexadecimal signature value + * @see https://developer.mozilla.org/ja/docs/Web/API/SubtleCrypto/sign + * @example + * await signHex("SHA256withECDSA", prvkey, "616161") -> "631b3f..." + */ +export async function signHex(alg: string, key: CryptoKey, hData: string): Promise { + //console.log(key); + const keyalgname = key.algorithm.name; + const u8aData = new Uint8Array(hextoBA(hData)); + let param: AlgorithmIdentifier | RsaPssParams | EcdsaParams; + if (keyalgname == "RSASSA-PKCS1-v1_5") { + param = { name: keyalgname } as AlgorithmIdentifier; + } else if (keyalgname == "RSA-PSS") { + param = { name: keyalgname, saltLength: 32 } as RsaPssParams; + } else { // if (keyalgname == "ECDSA") + param = { + name: keyalgname, + namedCurve: "P-256", + hash: { name: sigAlgToHashAlg(alg) } + } as EcdsaParams; + } + const abSig = await crypto.subtle.sign(param, key, u8aData); + return ArrayBuffertohex(abSig); +} + +/** + * verify signature with specified public key, algorithm and data + * @param alg - signature algorithm name (ex. SHA256withRSA) + * @param key - public key object + * @param hSig - hexadecimal signature value + * @param hData - hexadecimal data to be verified + * @param sigopt - salt length for RSA-PSS or curve name for ECDSA + * @return true if signature is valid + * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify + * @example + * await verifyHex("SHA256withECDSA", pubkey, "91ac...", "616161") -> true + */ +export async function verifyHex(alg: string, key: CryptoKey, hSig: string, hData: string, sigopt?: number | string): Promise { + const keyalgname = key.algorithm.name; + let param: AlgorithmIdentifier | RsaPssParams | EcdsaParams; + if (keyalgname == "RSASSA-PKCS1-v1_5") { + param = { name: keyalgname } as AlgorithmIdentifier; + } else if (keyalgname == "RSA-PSS") { + let len; + if (sigopt == undefined) { + len = getDefaultSaltLength(alg); + } else { + len = sigopt; + } + param = { name: keyalgname, saltLength: len } as RsaPssParams; // , saltLength: 32 + } else { // keyalgname == "ECDSA" + param = { + name: keyalgname, + namedCurve: sigopt, + hash: sigAlgToHashAlg(alg) + } as EcdsaParams; + } + const u8aSig = new Uint8Array(hextoBA(hSig)); + const u8aData = new Uint8Array(hextoBA(hData)); + return await crypto.subtle.verify(param, key, u8aSig, u8aData); +} + +function getDefaultSaltLength(alg: string) { + switch (alg) { + case "SHA1withRSAandMGF1": + return 20; + case "SHA256withRSAandMGF1": + return 32; + case "SHA384withRSAandMGF1": + return 48; + case "SHA512withRSAandMGF1": + return 64; + default: + throw new Error(`salt not supported for: ${alg}`); + } +} + +// == import PEM private/public key =========================== +/** + * import key from PEM private/public key string + * @param pem - PEM PKCS#8 private key or public key string + * @param alg - signature algorithm (SHA{1,224,256,384,512}with{RSA,RSAandMGF1,ECDSA}) + * @return CryptoKey object of W3C Web Crypto API + * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey + * @description + * This function import a CryptoKey object from PEM key file. + * @example + * let key = await importPEM("-----BEGIN PRIVATE...", "SHA256withRSA"); + */ +export async function importPEM(pem: string, alg: string, sigopt?: number | string): Promise { + const pemab: ArrayBuffer = hextoArrayBuffer(pemtohex(pem)); + const format: "pkcs8" | "spki" = getImportFormat(pem); + if (format == "pkcs8") { + const key = await crypto.subtle.importKey( + "pkcs8", + pemab, + getImportAlgorithm(pem, alg, sigopt), + true, + ["sign"] + ); + return key; + } else { // "spki" + const key = await crypto.subtle.importKey( + "spki", + pemab, + getImportAlgorithm(pem, alg, sigopt), + true, + ["verify"] + ); + return key; + } +} + +function getImportAlgorithm(pem: string, alg: string, sigopt?: number | string): AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams { + const matchResult = alg.match(/^SHA(1|224|256|384|512)with(RSA|RSAandMGF1|ECDSA)$/); + if (matchResult == null) { + throw new Error(`algorithm not supported: ${alg}`); + } + + if (matchResult[2] == "RSA") { + return { + name: "RSASSA-PKCS1-v1_5", + hash: { name: "SHA-" + matchResult[1] } + } as AlgorithmIdentifier; + } else if (matchResult[2] == "RSAandMGF1") { + return { + name: "RSA-PSS", + hash: { name: "SHA-" + matchResult[1] } + } as RsaHashedImportParams; + } else { // "ECDSA": + return { + name: "ECDSA", + namedCurve: sigopt + } as EcKeyImportParams; + } +} + +function getImportKeyUsage(pem: string): Array { + if (pem.indexOf("-BEGIN PRIVATE KEY-") != -1) return ["sign"]; + if (pem.indexOf("-BEGIN PUBLIC KEY-") != -1) return ["verify"]; + throw new Error("keyUsage for importKey in PEM not supported"); +} + +function getImportFormat(pem: string): "pkcs8" | "spki" { + if (pem.indexOf("-BEGIN PRIVATE KEY-") != -1) return "pkcs8"; + if (pem.indexOf("-BEGIN PUBLIC KEY-") != -1) return "spki"; + throw new Error("format for importKey in PEM not supported"); +} + +export function sigAlgToHashAlg(alg: string): string | null { + const matchResult = alg.match(/^SHA(1|224|256|384|512)with/); + if (matchResult == null) return null; + return "SHA-" + matchResult[1]; +} + +/** + * convert ECDSA signature value from RS concatinated to ASN.1 encoded + * @param hRS - hexadecimal string of R and S concatinated signature value + * @return ASN.1 DER encoded ECDSA signature value + * @description + * ECDSA signature value has two types of encoding: + * - R and S value concatinated encoding used in W3C Web Crypto API or JSON Web Signature. + * - ASN.1 SEQUENCE of INTEGER R and S value used in OpenSSL + * + * This function convert a ECDSA signature encoding from + * concatinated to ASN.1. This function supports ECDSA signatures by P-256, P-384 and P-521. + * @example + * sigRStoASN1(" + * 69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060 + * 76ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f") + * -> + * "3044 + * 0220 + * 69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060 + * 0220 + * 76ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f" + */ +export function sigRStoASN1(hRS: string): string { + const rslen: number = hRS.length / 2; + if (rslen != 64 && rslen != 96 && rslen != 132 && ! ishex(hRS)) { + throw new Error(`argument is not EC P-256|384|521 RS concat signature: rslen=${rslen}`); + } + + const hR: string = pospad(hRS.slice(0, rslen)); + const hS: string = pospad(hRS.slice(rslen)); + const json = { t: "seq", v: [ + { t: "int", v: hR }, + { t: "int", v: hS } + ] }; + const hASN1 = getASN1(json); + return hASN1; +} + +/** + * generate a secure random hexadecimal string + * @param nbyte - length of random bytes + * @return hexadecimal string of generated random bytes + * @description + * This function generates a secure random hexadecimal string + * with specified bytes by [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) + * which uses a pseudo-random number generator(PRNG) algorithm. + * @example + * getSecureRandom(3) -> "f73ad5" + * getSecureRandom(3) -> "d431c6" + * getSecureRandom(256) -> "147ac8..." (string length will be 512=256*2) + */ +export function getSecureRandom(nbyte: number): string { + const ab: ArrayBuffer = new ArrayBuffer(nbyte); + const u8a: Uint8Array = new Uint8Array(ab); + crypto.getRandomValues(u8a); + return ArrayBuffertohex(ab); +} + +/** + * generate new HMAC key with specified HMAC algorithm + * @param alg - HMAC algorithm ("hmacSHA{1,256,384,512}") + * @return hexadecimal string of HMAC key + * @description + * This function generates a HMAC key with specified HMAC + * algorithm with crypto.getRandomValues not + * crypto.subtle.generateKey. Its byte length will be + * the same as generateKey as following: + * + * - hmacSHA1, hmacSHA256: 64 bytes + * - hmacSHA384, hmacSHA512: 128 bytes + * + * @example + * getNewHMACKey("hmacSHA256") -> "8ab134..." (64 bytes) + * getNewHMACKey("hmacSHA512") -> "374cdf..." (128 bytes) + */ +export function getNewHMACKey(alg: string): string { + const match = alg.match(/^hmacSHA(1|256|384|512)$/); + if (match == null) { + throw new Error(`unsupported algorithm: ${alg}`); + } + const hashlen = match[1]; + if (hashlen == "1" || hashlen == "256") return getSecureRandom(64); + return getSecureRandom(128); // for SHA-384 or SHA-512 +} + +/** + * get HMAC key object + * @param alg - HMAC algorithm name ("hmacSHA{1,256,384,512}") + * @param hKey - hexadecimal string of HMAC key + * @return HMAC key object + * @description + * This function generates CryptoKey object with specified + * HMAC algorithm and a hexadecimal string of HMAC key value. + * @see getNewHMACKey + * @example + * await getHMACKey("hmacSHA256", "3b6839...") -> CryptoKey object + */ +export async function getHMACKey(alg: string, hKey: string): Promise { + if (! ishex(hKey)) throw new Error("hKey is not a hexadecimal"); + const match = alg.match(/^hmacSHA(1|256|384|512)$/); + if (match == null) throw new Error(`HMAC alg not supported: ${alg}`); + + const key = await crypto.subtle.importKey( + "raw", + hextoArrayBuffer(hKey), + { name: "HMAC", hash: { name: `SHA-${match[1]}` } }, + true, + ["sign", "verify"] + ); + return key; +} + +/** + * sign hexadecimal data with HMAC + * @param alg - HMAC algorithm name ("hmacSHA{1,256,384,512}") + * @param key - CryptoKey object or hexadecimal string of HMAC key + * @param hData - hexadecimal string data to be signed + * @return hexadecimal string of HMAC signature + * @see {@link verifyHMACHex} + * @example + * await signHMAXHex("hmacSHA256", "9abf1245...", "616161") -> "7c8ffa..." + */ +export async function signHMACHex(alg: string, key: string | CryptoKey, hData: string): Promise { + const keyobj: CryptoKey + = (typeof key == "object") ? key : await getHMACKey(alg, key as string); + const sigab: ArrayBuffer = await crypto.subtle.sign( + "HMAC", + keyobj, + hextoArrayBuffer(hData) + ); + return ArrayBuffertohex(sigab); +} + +/** + * verify HMAC signature + * @param alg - HMAC algorithm name ("hmacSHA{1,256,384,512}") + * @param key - CryptoKey object or hexadecimal string of HMAC key + * @param hSig - hexadecimal string of HMAC signature value + * @param hData - hexadecimal string of data to be verified + * @return true if the signature is valid + * @see {@link signHMACHex} + * @example + * await verifyHMACHex("hmacSHA256", "9abf1245...", "7ff2bc...", "616161") -> true + */ +export async function verifyHMACHex(alg: string, key: string | CryptoKey, hSig: string, hData: string): Promise { + const keyobj: CryptoKey + = (typeof key == "object") ? key : await getHMACKey(alg, key as string); + const result = await crypto.subtle.verify( + "HMAC", + keyobj, + hextoArrayBuffer(hSig), + hextoArrayBuffer(hData) + ); + return result; +} + +/* +256 col64 +69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060 +76ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f +384 col96 +cb6c3115a81bfb7581df9bd05e4116ed90f483fdbe03c8c8204c6d2a9bba7520580dfb86f5649ad2de5fce59b67b4b61 +59924fcd38c995d782d33f1750134cbef6e609558fa6d7e6a0eff7d32b90a48df5eb9fed839fa492cb9da50a017a0f12 +521 col132 +014e8d5d7ea8494a0b4e48372b76e61bee7fdd0db7463aee4551e9b7df15f8a9d6216c478b046406450d8b0cbb97098b126ac6362800384d726aa230c579092e7e3b +01e01a525804b4095d5cd57c2ca031dab907c2d08dc792b93261ec2e656058a86d2479cea115b26bc69e3e6894b0a9dcd0d8f65aa6a69f499a02980bd3c8ca352af4 + */ diff --git a/src/index.test.mts b/src/index.test.mts new file mode 100644 index 0000000..cfb1bb9 --- /dev/null +++ b/src/index.test.mts @@ -0,0 +1,412 @@ +import { describe, expect, test } from "bun:test"; +import { hashhex, hashutf8, hashrstr, importPEM, signHex, verifyHex, sigAlgToHashAlg, sigRStoASN1, getSecureRandom, getNewHMACKey, getHMACKey, signHMACHex, verifyHMACHex } from "./index.mts"; + +// == hash test ========== +const AAA256 = "9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0"; // =SHA256("aaa") + +test("hashex", async () => { + expect(await hashhex("SHA-256", "616161")).toBe(AAA256); +}); + +test("hashrstr", async () => { + expect(await hashrstr("SHA-256", "aaa")).toBe(AAA256); +}); + +test("hashutf8", async () => { + expect(await hashutf8("SHA-256", "aaa")).toBe(AAA256); +}); + +// == importpem test ========== + +test("importPEM RSA private1", async () => { + const key = await importPEM(PRVR1024, "SHA256withRSA"); + expect(key.type).toBe("private"); + expect(key.algorithm.name).toBe("RSASSA-PKCS1-v1_5"); + expect(key.algorithm.modulusLength).toBe(1024); + expect(key.algorithm.hash).toEqual({name:"SHA-256"}); + expect(key.usages).toEqual(["sign"]); +}); + +const SIGAAARSA1024 = "01b85ed1b6669b4d43082521d7b7db481a5ac75016792e2465de6ffb0426bdb85774ebf848f739f79b42c4d584b99dd8c5242479ae19d2a50cf5dee9a854ae56560faf83200c377d131fd983b6219ef4be2b00215b261d3619e73d641afb23892238a51744e2384ec5a7b33072b5b5704a12f9076559f7a7e6858c73c78c3104"; +test("signHex", async () => { + const key = await importPEM(PRVR1024, "SHA256withRSA"); + const hSig = await signHex("SHA256withRSA", key, "616161"); + expect(hSig).toBe(SIGAAARSA1024); + //console.log(sig); + //expect(true).toEqual(true); + + //const key2 = await importPEM(PRVECPEM1, "SHA256withECDSA", "P-256"); + //const hSig2 = await signHex("SHA256withECDSA", key2, "616161", "P-256"); + //console.log(hSig2); +}); + +test("importPEM RSA public1", async () => { + const key = await importPEM(PUBR1024, "SHA256withRSA"); + expect(key.type).toBe("public"); + expect(key.algorithm.name).toBe("RSASSA-PKCS1-v1_5"); + expect(key.algorithm.modulusLength).toBe(1024); + expect(key.algorithm.hash).toEqual({name:"SHA-256"}); + expect(key.usages).toEqual(["verify"]); +}); + +test("importPEM RSAPSS private1", async () => { + const key = await importPEM(PRVR1024, "SHA256withRSAandMGF1"); + expect(key.type).toBe("private"); + expect(key.algorithm.name).toBe("RSA-PSS"); + expect(key.algorithm.modulusLength).toBe(1024); + expect(key.algorithm.hash).toEqual({name:"SHA-256"}); + expect(key.usages).toEqual(["sign"]); +}); + +test("importPEM RSA public1 various hash alg SHA-1/224/256/384/512", async () => { + let key = await importPEM(PUBR1024, "SHA1withRSA"); + expect(key.algorithm.hash).toEqual({name:"SHA-1"}); + key = await importPEM(PUBR1024, "SHA224withRSA"); + expect(key.algorithm.hash).toEqual({name:"SHA-224"}); + key = await importPEM(PUBR1024, "SHA256withRSA"); + expect(key.algorithm.hash).toEqual({name:"SHA-256"}); + key = await importPEM(PUBR1024, "SHA384withRSA"); + expect(key.algorithm.hash).toEqual({name:"SHA-384"}); + key = await importPEM(PUBR1024, "SHA512withRSA"); + expect(key.algorithm.hash).toEqual({name:"SHA-512"}); +}); + +// RFC 9500 test EC P-256 private +const PRVECPEM1 = `-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg5stb3YCqRa6clejB +VHZnn/7JU8FoUecR50OTlYnGT8GhRANCAARCJUj4j7eC/7Xso3REUscqHlWPvW9z +vl5I6TIyzEXFsWxM0QxMuNW4oXE56UiCyJklcpk0JfQUGat+kKQqSUJy +-----END PRIVATE KEY-----`; + +// RFC 9500 test EC P-256 public +const PUBECPEM1 = `-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQiVI+I+3gv+17KN0RFLHKh5Vj71v +c75eSOkyMsxFxbFsTNEMTLjVuKFxOelIgsiZJXKZNCX0FBmrfpCkKklCcg== +-----END PUBLIC KEY-----`; + +test("importPEM EC P-256 private1", async () => { + const key = await importPEM(PRVECPEM1, "SHA256withECDSA", "P-256"); + expect(key.type).toBe("private"); + expect(key.algorithm.name).toBe("ECDSA"); + expect(key.algorithm.namedCurve).toBe("P-256"); + expect(key.usages).toEqual(["sign"]); +}); + +test("importPEM EC P-256 public1", async () => { + const key = await importPEM(PUBECPEM1, "SHA256withECDSA", "P-256"); + expect(key.type).toBe("public"); + expect(key.algorithm.name).toBe("ECDSA"); + expect(key.algorithm.namedCurve).toBe("P-256"); + expect(key.usages).toEqual(["verify"]); +}); + +test("signHex verifyHex RSA", async () => { + const hData = "616161"; + const prvkey = await importPEM(PRVR1024, "SHA256withRSA"); + const hSig = await signHex("SHA256withRSA", prvkey, hData); + + const pubkey = await importPEM(PUBR1024, "SHA256withRSA"); + expect(await verifyHex("SHA256withRSA", pubkey, hSig, hData)).toBe(true); +}); + +test("signHex verifyHex RSA-PSS", async () => { + const hData = "616161"; + const prvkey = await importPEM(PRVR1024, "SHA256withRSAandMGF1"); + const hSig = await signHex("SHA256withRSAandMGF1", prvkey, hData); + + const pubkey = await importPEM(PUBR1024, "SHA256withRSAandMGF1"); + expect(await verifyHex("SHA256withRSAandMGF1", pubkey, hSig, hData)).toBe(true); +}); + +test("signHex verifyHex EC P-256", async () => { + const hData = "616161"; + const prvkey = await importPEM(PRVECPEM1, "SHA256withECDSA", "P-256"); + const hSig = await signHex("SHA256withECDSA", prvkey, hData, "P-256"); + + const pubkey = await importPEM(PUBECPEM1, "SHA256withECDSA", "P-256"); + expect(await verifyHex("SHA256withECDSA", pubkey, hSig, hData, "P-256")).toBe(true); +}); + +test("sigAlgToHashAlg", () => { + expect(sigAlgToHashAlg("SHA1withRSA")).toBe("SHA-1"); + expect(sigAlgToHashAlg("SHA512withECDSA")).toBe("SHA-512"); + expect(sigAlgToHashAlg("MD5withRSA")).toBe(null); +}); + +describe("verifyHex jwt.io generated signatures interop", async () => { + test("SHA256withRSAandMGF1 2048 salt=default mgf1=default", async () => { + // testrsa2048.jwtio.ps256.* + const TBSHEX = "65794a68624763694f694a51557a49314e694973496e523563434936496b705856434a392e65794a7a645749694f6949784d6a4d304e5459334f446b7749697769626d46745a534936496b7076614734675247396c4969776959575274615734694f6e527964575573496d6c68644349364d5455784e6a497a4f5441794d6e30"; + const SIGHEX = "82c8252d01888522910e8285874263ca100c15f7d7b672f02d4598b545f9b5298ac66129f5b6fba00c399b73be2964572e0e00449225079ab7e84e9ee457947722092ee8c4c26fe6746adb820f4f7b697b84aca3140a18f3fed4ae8ba7f1add764cbf00d4f9bcbead319e1183458f8c6787702f812c1e38e0c0904dfa90c7210e2c68c99dec4b0162e190a5236b5e1f0bbfbbbd7edf3bc03d7789e8f70026437dc53681d05bb3b26cd0ec3800e73de9ebb04b37414ef056653f7959e7d1c26fa9d0e28c92af9c39c63da5654bb8efce887f34ec17d77c06923dedeebd2db138afc97b8a47d1c8f46248ed8aea3aa611736f0a56568ce823f1864a82d219094f1"; + const pubR2048 = await importPEM(PUBR2048, "SHA256withRSAandMGF1"); + expect(await verifyHex("SHA256withRSAandMGF1", pubR2048, SIGHEX, TBSHEX)).toBe(true); + }); + test("SHA384withECDSA", async () => { + // testecp384.jwtio.es384.* + const TBSHEX = "65794a68624763694f694a46557a4d344e434973496e523563434936496b705856434a392e65794a7a645749694f6949784d6a4d304e5459334f446b7749697769626d46745a534936496b7076614734675247396c4969776959575274615734694f6e527964575573496d6c68644349364d5455784e6a497a4f5441794d6e30"; + const SIGHEX = "d587d8a67e4f29adfe85c79e9ff0bb1b5428d1c3a19934d651b0fd918a3d33881e85e013859a09c91abeac7aa2ef9ae6ab756c4d0f42c9747c788fb900014ae1e7583fe6f3cb80093e27afae629faa5bb41cf5b11ec5d13dd082af527ba5bd82"; + const pubE384 = await importPEM(PUBE384, "SHA384withECDSA", "P-384"); + expect(await verifyHex("SHA384withECDSA", pubE384, SIGHEX, TBSHEX, "P-384")).toBe(true); + }); +}); + +describe("verifyHex OpenSSL generated signatures interop", async () => { + test("SHA256withRSA 1024", async () => { + const pubR1024 = await importPEM(PUBR1024, "SHA256withRSA"); + expect(await verifyHex("SHA256withRSA", pubR1024, SIGOSSR1024, AAAHEX)).toBe(true); + }); + test("SHA256withRSA 2048", async () => { + const pubR2048 = await importPEM(PUBR2048, "SHA256withRSA"); + expect(await verifyHex("SHA256withRSA", pubR2048, SIGOSSR2048, AAAHEX)).toBe(true); + }); + test("SHA512withRSA 4096", async () => { + const pubR4096 = await importPEM(PUBR4096, "SHA512withRSA"); + expect(await verifyHex("SHA512withRSA", pubR4096, SIGOSSR4096, AAAHEX)).toBe(true); + }); + test("SHA1withECDSA P-256", async () => { + const pubE256S1 = await importPEM(PUBE256, "SHA1withECDSA", "P-256"); + expect(await verifyHex("SHA1withECDSA", pubE256S1, SIGOSSE256S1, AAAHEX, "P-256")).toBe(true); + }); + test("SHA256withECDSA P-256", async () => { + const pubE256 = await importPEM(PUBE256, "SHA256withECDSA", "P-256"); + expect(await verifyHex("SHA256withECDSA", pubE256, SIGOSSE256, AAAHEX, "P-256")).toBe(true); + }); + test("SHA384withECDSA P-384", async () => { + const pubE384 = await importPEM(PUBE384, "SHA384withECDSA", "P-384"); + expect(await verifyHex("SHA384withECDSA", pubE384, SIGOSSE384, AAAHEX, "P-384")).toBe(true); + }); + test("SHA1withECDSA P-521", async () => { + const pubE521S1 = await importPEM(PUBE521, "SHA1withECDSA", "P-521"); + expect(await verifyHex("SHA1withECDSA", pubE521S1, SIGOSSE521S1, AAAHEX, "P-521")).toBe(true); + }); + /* + test("SHA256withECDSA P-521", async () => { + const pubE521S2 = await importPEM(PUBE521, "SHA256withECDSA", "P-521"); + expect(await verifyHex("SHA256withECDSA", pubE521S2, SIGOSSE521S2, AAAHEX, "P-521")).toBe(true); + }); // エラー + test("SHA384withECDSA P-521", async () => { + const pubE521S3 = await importPEM(PUBE521, "SHA384withECDSA", "P-521"); + expect(await verifyHex("SHA384withECDSA", pubE521S3, SIGOSSE521S3, AAAHEX, "P-521")).toBe(true); // エラー + }); + */ + test("SHA512withECDSA P-521", async () => { + const pubE521 = await importPEM(PUBE521, "SHA512withECDSA", "P-521"); + expect(await verifyHex("SHA512withECDSA", pubE521, SIGOSSE521, AAAHEX, "P-521")).toBe(true); + }); + + test("SHA256withRSAandMGF1 2048 salt=default mgf1=default", async () => { + const pubR2048 = await importPEM(PUBR2048, "SHA256withRSAandMGF1"); + expect(await verifyHex("SHA256withRSAandMGF1", pubR2048, SIGOSSP2048D2SDMD, AAAHEX)).toBe(true); + }); + + test("SHA384withRSAandMGF1 2048 salt=default mgf1=default", async () => { + const pubR2048 = await importPEM(PUBR2048, "SHA384withRSAandMGF1"); + expect(await verifyHex("SHA384withRSAandMGF1", pubR2048, SIGOSSP2048D3SDMD, AAAHEX)).toBe(true); + }); + + test("SHA512withRSAandMGF1 2048 salt=default mgf1=default", async () => { + const pubR2048 = await importPEM(PUBR2048, "SHA512withRSAandMGF1"); + expect(await verifyHex("SHA512withRSAandMGF1", pubR2048, SIGOSSP2048D5SDMD, AAAHEX)).toBe(true); + }); +}); + +describe("sigRStoASN1", () => { + test("P-256 RS Sig", () => { + expect(sigRStoASN1(SIGOSSE256)).toBe("3044022069c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd060022076ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f"); + }); + test("P-384 RS Sig", () => { + expect(sigRStoASN1(SIGOSSE384)).toBe("3065023100cb6c3115a81bfb7581df9bd05e4116ed90f483fdbe03c8c8204c6d2a9bba7520580dfb86f5649ad2de5fce59b67b4b61023059924fcd38c995d782d33f1750134cbef6e609558fa6d7e6a0eff7d32b90a48df5eb9fed839fa492cb9da50a017a0f12"); + }); + test("P-521 RS Sig", () => { + expect(sigRStoASN1(SIGOSSE521)).toBe("30818802420185d9deae536fdd568ed6174ae4481a5d447b59c7bfb424d0b14b6bc098622ecaed9d3e967c541b717bef7b293d3c3ffa86cdedad31cfad20ef3e8f54ac3fa2078f024201d6c72311db50b27039a5b6d664e9ec423c501841eff48a7f35882c18b5a0ba2a928449f282448eb4af9f7ed60813f51862a5ffcefb3e6a8805faf2827bdfd4f246"); + }); +}); + +test("getSecureRandom", () => { + expect(getSecureRandom(8).length).toBe(16); + expect(getSecureRandom(256).length).toBe(512); +}); + +test("getNewHMACKey", () => { + expect(getNewHMACKey("hmacSHA1").length).toBe(128); + expect(getNewHMACKey("hmacSHA256").length).toBe(128); + expect(getNewHMACKey("hmacSHA384").length).toBe(256); + expect(getNewHMACKey("hmacSHA512").length).toBe(256); +}); + +test("getHMACKey", async () => { + const hKey = "a1020304050607080900b1020304050607080900c1020304050607080900d1020304050607080900e1020304050607080900f1020304050607080900a1020304"; // 64 bytes + const key: CryptoKey = await getHMACKey("hmacSHA256", hKey); + //console.log(key); + expect(typeof key).toBe("object"); + expect(key.algorithm.name).toBe("HMAC"); + expect(key.algorithm.hash.name).toBe("SHA-256"); + expect(key.algorithm.length).toBe(512); +}); + +describe("signHMACHex OpenSSL mac command interop", async () => { + test("SHA1", async () => { + expect(await signHMACHex("hmacSHA1", HMACKEY1, "616161")).toBe(SIGOSSHS1); + }); + test("SHA256", async () => { + expect(await signHMACHex("hmacSHA256", HMACKEY1, "616161")).toBe(SIGOSSHS256); + }); + test("SHA384", async () => { + expect(await signHMACHex("hmacSHA384", HMACKEY1, "616161")).toBe(SIGOSSHS384); + }); + test("SHA512", async () => { + expect(await signHMACHex("hmacSHA512", HMACKEY1, "616161")).toBe(SIGOSSHS512); + }); +}); + +describe("verifyHMACHex OpenSSL mac command interop", async () => { + test("SHA1", async () => { + expect(await verifyHMACHex("hmacSHA1", HMACKEY1, SIGOSSHS1, "616161")).toBe(true); + }); + test("SHA256", async () => { + expect(await verifyHMACHex("hmacSHA256", HMACKEY1, SIGOSSHS256, "616161")).toBe(true); + }); + test("SHA384", async () => { + expect(await verifyHMACHex("hmacSHA384", HMACKEY1, SIGOSSHS384, "616161")).toBe(true); + }); + test("SHA512", async () => { + expect(await verifyHMACHex("hmacSHA512", HMACKEY1, SIGOSSHS512, "616161")).toBe(true); + }); +}); + +describe("RFC 7797 sample JWS signature interop", async () => { + test("4.1 HS256", async () => { + expect(await verifyHMACHex("hmacSHA256", "0323354b2b0fa5bc837e0665777ba68f5ab328e6f054c928a90f84b2d2502ebfd3fb5a92d20647ef968ab4c377623d223d2e2172052e4f08c0cd9af567d080a3", "e66bdf3aba0bfa0ec7caa268a337a19ac6aa9af4d8184ab98d3235815be81284", "65794a68624763694f694a49557a49314e694a392e4a4334774d67")).toBe(true); + }); +}); + + +// test data ============================================================= +const AAAHEX = "616161"; + +// RFC 9500 test keys ================================================= + +const PRVR1024 = `-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALDRg1Koj1PVUW9G +wg56Nn196IrPVKAZ9t71erm0TO3bIkKxvKD7G1y4KzA2F2pjkDVk3sbrQdsvj8eH +9OUuEUnjM0dXKXP2YMPHfKngghwraVvnrp19MPQHkRD0iq5vi3AtR0spAIF/KGYk +m+wSorGbgnhBaAj4GuH8+bd3imI/AgMBAAECgYBILp+PpOQt8w11gctCob2Q6U9/ +Kzh+y1qulkPtf59QEn8f/vLkPN5ksYJgAhT5B4Ada/pN9khCNF5btDLTREUl2DAW +VMVEKwpeEbnH4gH6MvQauvTwpuA88ODLgmbGKtEdlW1TyUZuSJlf6iYMhTbwQcs1 +YvqsURxNZqj+0RGykQJBAOnYbk3DSphafsdab1SnXORROeRSQLOGq3Edt5G82YcY +oTuvIYwkSTZGaAdWy1Cmy+4VjiUhRJkSMBwNQUkRGEUCQQDBkfo7VQs5GnywcoN2 +J3KV5hxlTwvvL1jc5clioQt9118GAVRl5VB25GYmPuvK7SDS66s5MT6LxWcyD+iy +3GKzAkEA5zrgN3y4slYprq66D5c+v3WiLSc4W0z7Ees0raNz5aZxKDdQkOcAje6o +xzkH6kREurQNzqFK16GoeNSSjdGdkQJAQZl5FhZyIT4Kt7l3N9mSiZ5cTTEGuF5x +XRs6roQpYtJUT7KvqYCXTlOFEr0MJ89I6nIXquA3dCLIID0n/UWW5QJBALmdf49N +TUVfH7pGLZkKLoSMQowevuAdwAGEyKdlg603n2mtr1R1VDD2PEJT0bt4zJvSMmQ0 +AIC4TBqRfeCLbts= +-----END PRIVATE KEY-----`; + +// RFC 9500 test RSA 1024 public +const PUBR1024 = `-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCw0YNSqI9T1VFvRsIOejZ9feiK +z1SgGfbe9Xq5tEzt2yJCsbyg+xtcuCswNhdqY5A1ZN7G60HbL4/Hh/TlLhFJ4zNH +Vylz9mDDx3yp4IIcK2lb566dfTD0B5EQ9Iqub4twLUdLKQCBfyhmJJvsEqKxm4J4 +QWgI+Brh/Pm3d4piPwIDAQAB +-----END PUBLIC KEY-----`; + +const PUBR2048 = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsPnoGUOnrpiSqt4XynxA ++HRP7S+BSObI6qJ7fQAVSPtRkqsotWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTf +Mul8b/CZjP2Ob0LdpYrNH6l5hvFE89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92 +UE68mOyUVXGweJIVDdxqdMoPvNNUl86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/ +LUK43YvJh+rhv4nKuF7iHjVjBd9sB6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKN +e6kUhKJ1luB7S27ZkvB3tSTT3P593VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9T +EwIDAQAB +-----END PUBLIC KEY-----`; + +const PUBR4096 = `-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs4tJYOY75qjbqJqCl47x +9jJE5Vd9jPWGFtXKV1nUnMjZNsM4qjy5sRHBSX5bUa9pLyYR5on3Z1SAwLD0w2VP +Q6+F/oyK1zTgQqitoF/XZQjgC6D3VsNEO76DPqfRANT7Nn7r1gvbZIZ3/H3rlCRN +rRr47tHGWBLAPnxz9/NY6UG8ZkWP97uXpJqYoRgH4CwaO5rTOlc64YDh/0Mq5VgM +ycq/q2AvMlvNoJfoe8em1040qH1gikP+suT/8fS452hqmEddtRpuvQgXKldBd0kk +iyFVyLkG4NVA6Mso9MAK3J/kdYoaw2SrOeThVSiYVEQVP+7GrUxTSLLjj/VQ9fpY +M5eTNzDICIG/Ee7o/jhtW1EoSamDmUOr89lyIHaXuOwkEaJhnVXKBCM8WiztxvKG +2CnQ6Dcge3ZSmqJEhyEmjcAVC7ewfnMxOnE+WJW6rzrf+mA5WMVn+FzyWx2AondW +ow0aUKHkaY7amhIrsKp6YPfNImyxFlz8+cqDCmBswPsUh/JJ5eDHHIhibFcSgIHe +dsEjhLbUSLZ/DnEjru90qIWWA3R1VIPykKfeZkZeInsrFzGPikkFKwFF+6KDdyvC +mltYEqzO46tigXAZ5UgH8oiXEre48wO6X+FH+cLzQ0q3A8HZRnNDgqCjU/Tgy76i +aku/Ic6eteedR1fX3gJ/IOUCAwEAAQ== +-----END PUBLIC KEY-----`; + +const PUBE256 = `-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQiVI+I+3gv+17KN0RFLHKh5Vj71v +c75eSOkyMsxFxbFsTNEMTLjVuKFxOelIgsiZJXKZNCX0FBmrfpCkKklCcg== +-----END PUBLIC KEY-----`; + +const PUBE384 = `-----BEGIN PUBLIC KEY----- +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEWwkBuIUjKW65GdUP+hqcs3S8TUCVhigr +/soRsdla27VHNK9XC/grcijPImvPTCXdvP47GjrTlDDv92Ph1o0uFR2Rcgt3lbWN +prNGOWE6j7m1qNpIxnRxF/mRnoQk837I +-----END PUBLIC KEY-----`; + +const PUBE521 = `-----BEGIN PUBLIC KEY----- +MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB0P1yV6hMdH9WJXXAc4Xb6/L1K+pY +CD24L90VMdiq48yHX/Av9/otomDY62LW0vXWSSeOMhc2oGKMu7MDCLbmGNsA9irS +BMZGA1m8gYq4lhvw8PwOxaropCgXPOVvAN6bFXweXILGT1Yvyt78Skwo9tNCzz72 +FvyC0ztyhckh8r82/dg= +-----END PUBLIC KEY-----`; + +// test signatures generated with OpenSSL and RFC 9500 test private keys ==== + +// testrsa1024.aaa.sha256.sig +const SIGOSSR1024 = "01b85ed1b6669b4d43082521d7b7db481a5ac75016792e2465de6ffb0426bdb85774ebf848f739f79b42c4d584b99dd8c5242479ae19d2a50cf5dee9a854ae56560faf83200c377d131fd983b6219ef4be2b00215b261d3619e73d641afb23892238a51744e2384ec5a7b33072b5b5704a12f9076559f7a7e6858c73c78c3104"; + +// testrsa2048.aaa.sha256.sig +const SIGOSSR2048 = "18c171461718df870ff04fefa5be19fdffe85f1a41435cbc73ed654b41f693ce02679adbf3a08eca3f595e21c0ad9a24b65ac33c82399af8f4468ae30cf81f07457a24836508d9da2b3a3df4a738c186a153b4afcc78a3b37ee0604d18f17dc67ae586d5c52ad27b7af959eccb8a1d633cccf86182fbfa45c0bb09661105da56b719c177045decfb507e54a34fae6bf8ea9c2f975172cb99d77d18bdc23a3e0f26a65dcc36609fe339d383884a64be363c21b6bc814bd55c4ff7c2f0d9f4eb51a31d219ba5a1ee700c96a95b8bee7b49ea0fb76660206752eb5f9fd472e49ca9b230614ab3e307a3d2a13bc9b093f063b75fff7089ddcbb9f81cd97e1a4369f3"; + +// testrsa4096.aaa.sha512.sig +const SIGOSSR4096 = "36f11c3c0dfdb74bfb88530b6712b86d6e5491688133314df35e1d65e350e4dd5411fa5c36b50b01526b273a19d57b37e37df4ca150b3f860e029a74d355ccef0173e1618bc5fd435d73067e878d3b7a26b03685d27761871f223154ac27231e37ce3cac111272c2bfb047c13ddfc1227c672b5a69a0fe32b3aa17153e90d8a15992af53222b009d053fcecf9a3fab75063e08c193d9832751ef753a1c5bae20043d5917ab8bcd4ce0d293e29af17be83ebc9937d11d6496998d4f01bf3bab9ae1057c6bf6a574483ac1272c1b8ace473eafb102a2ce455047262ad96142ea9779d0b9439a5bd2a9527e0f8374298bde0efb66e6d5ec535af6e7ce39744ffa99e9242b64ab07a32aeeb6a7d6bd2d7cfcaa6bc984e0c7bd7ed117d8de263c37ae9f84fd89d3add3ed572150899ebe89e3ebe8c2b2cfc3b4d5b25f3ad615d75bc317502fa42e4c0e109521d247d4a7170e82e433cc16adca981800b0ed2d365d1392c97eb37c0a92656213a90b91b4dcd4abba177c7f8a8e90ec0dbd6e4fabccf9c8d44e9f5c393f3ac01e4238424e6ac7f2f0e96fb0240c2bd522495afa58ceb084077cc7d278612891767e48dbd9e23b37dc7b611f12909c5a3952d31c9f1ef1ad53cba6e164f83cd8cf306abf40ffaa01053c920353b0ed9bf6c75c04926024bafdf31f20c3a245ea1531e2571e1e14fabb8458531c9365e42202316fc17efa"; + +// testecp256.aaa.sha1.sig +const SIGOSSE256S1 = "29d8716fd81ccbb579a4c5d14678f15250a70dc5dc8dc406e8f9dea240704256a343f16cedb33b9606acbbbb52d634d8b835a27a90b9f52f64c620fdcf0a1b34"; + +// testecp256.aaa.sha256.sig +const SIGOSSE256 = "69c3e2489cc23044f91dce1e5efab7a47f8c2a545cdce9b58e408c6a2aabd06076ba3d70771c00451adcf608d93f20cc79ccaf872f42028aa05ff57b14e5959f"; + +// testecp384.aaa.sha384.sig +const SIGOSSE384 = "cb6c3115a81bfb7581df9bd05e4116ed90f483fdbe03c8c8204c6d2a9bba7520580dfb86f5649ad2de5fce59b67b4b6159924fcd38c995d782d33f1750134cbef6e609558fa6d7e6a0eff7d32b90a48df5eb9fed839fa492cb9da50a017a0f12"; + +// testecp521.aaa.sha1.sig +const SIGOSSE521S1 = "014e8d5d7ea8494a0b4e48372b76e61bee7fdd0db7463aee4551e9b7df15f8a9d6216c478b046406450d8b0cbb97098b126ac6362800384d726aa230c579092e7e3b01e01a525804b4095d5cd57c2ca031dab907c2d08dc792b93261ec2e656058a86d2479cea115b26bc69e3e6894b0a9dcd0d8f65aa6a69f499a02980bd3c8ca352af4"; + +// testecp521.aaa.sha256.sig +//const SIGOSSE521S2 = "91a8506e50080b553c9aeb856e6eea6c1db842f68342c229d83b4ebb95067f0088947bb79f8624098de08c100416508eebc6502a42d2a624d59d9776197ed066ad26f9e457263c4eabba40d2ebb6b491700e74b593b64c18231a565c7261c75da2f091e387309943f9afaf2b3fc18fbe1cec86eff156e0c52fe749016ca58a01319d"; +const SIGOSSE521S2 = "0187ee6ba73303c5c7bad0149b46142d621110aa676ca546ec592b3c05763004300455843e25df94148d6ef6859c8f70fe82460c7b7f97497304a69cc9b2a4ed654fb9161809a862ac2c9fc8385b2f2794d721ead5bae243749caac84e00c1dd8c0c2438d80549eeb44ac46626ad8367c6018f71a2dd1de0e5bfeeaf42d332f2b83e9d"; + +// testecp521.aaa.sha384.sig +//const SIGOSSE521S3 = "01afd85abd294d62d28b885c1c5e72384a681699240b6718b6942a8e4d50b03a28dd4494be8ab6d94587d2dbf727eac87147d9bace6c76c21105081e15be944127553aab3c196daa568ac885464acc42530d4ad25611c2b9a068c6af40cc3070db9778c72266b3face25c0cf968aa114eb984a7d28a1f8d9d454a8467747a07d0c2851"; +const SIGOSSE521S3 = "0179991b37591cd500e7197f8fe4b7efc6e247fed3271ab71c482928ed86d998273ccb7641edd718e3eeec45b79f0ac9885a5f72d22b1ae7e4072b1332e3ecf6e1e6993e691f4043f30fb75fee54771239ded41628ee4968daedd4aa2d1a05f38db1372eefbf5f7b83314d8d34641fbc79546f456388af542e4c22d04580ca4ae7df22"; + +// testecp521.aaa.sha512.sig +const SIGOSSE521 = "0185d9deae536fdd568ed6174ae4481a5d447b59c7bfb424d0b14b6bc098622ecaed9d3e967c541b717bef7b293d3c3ffa86cdedad31cfad20ef3e8f54ac3fa2078f01d6c72311db50b27039a5b6d664e9ec423c501841eff48a7f35882c18b5a0ba2a928449f282448eb4af9f7ed60813f51862a5ffcefb3e6a8805faf2827bdfd4f246"; + +// testrsa2048.aaa.pss.d256.sdef.mdef.sig +const SIGOSSP2048D2SDMD = "7abd6e49b09715af2c373e27df13442e992fbf492010195eeab4527ae2206841ef8e410672c5c3d13567943803828554073ac82404d2e1f9a0dd0060f9f271fc97095ade34d6cefaf2e5dbe065e42bc062b17eb490b9a535d30a89b6fa09275a840012354180318d1aa8b30690f2a782a3f0c5b13c2b6c12b08f61df2537658b4f125d2685fea0b185dd0ab470b119960848c5d528f94b8868fb4034324f620b9cb2ae7c23dd64760ec66f6b2fc1cf1036c2f9e6b514a5643ce5983a94e9db06960debb219e6ed0a4271675fc6426d0f22cb995173759d4049f3680d8a6c49d1875bc8fd960849a29bc2afed2ac0d3a4c96cd20444c790849ab3390c0e0f9efb"; + +// testrsa2048.aaa.pss.d384.sdef.mdef.sig +const SIGOSSP2048D3SDMD = "555557dc928eb9c0d64f92ddf12e9d406e2405dc9d75ea4de44cec25a099f0935b5ce388b1b1cd4f771deafebdf78053f869115c85a97621db126a082ad116a74e40f39111c5b6e330583da6190b19f0cba1957f4b44263a40e74917e49e4f535654dfc9d453f7c2f80babdbb1a2df66ae05f06189b2f526e608e7cc28f03794f86db985ed105acb7fe74d43834f102a99a81f8f87ac262ed8cb5619f0a1cda8dc26a738fe34a28fb99fd57162b41e14c9c8d1b0f6b337edede1e4b8f24b0e6fb4a7eea5fae0e1d686c77c0b9b043ecaa11c1d520d50e1d03b9ea39b6c92e1b587fb81985a278783fb8c646114dcaca9180df6e5721123372dcc805c995cd240"; + +// testrsa2048.aaa.pss.d512.sdef.mdef.sig +const SIGOSSP2048D5SDMD = "ae0b11d54d4ad98fdb29165a67a72e2247c29428be64b8fa2054b68799748e127e71c72236a08f485ca53793b4b3452aaf0366e26ba02d8477b045d5c2e77e58ae2d2c7136f0a8009ba3a133d71e9216ffca98e6b408561753ea54263049782600dedb396d2a81b8ce80e7606c7b0428a320ef0855c3a7490867884d23563e3d0e1e423cd79920813df1747c136e211522e1f2a5fe9c02a4369047dfd8eb619860f66dce5e533ade66a8a3828a827824ce333bb0fe9f9d616ee9ddf535bd25cf6d2c2d8397529f6934e8f9afda7e7bcc848c15998232d9a2090bd413e18c3b16792b2da39f18815287330cb82dffcd4c31e4a1e6f7d143153a35ed36fd01de18"; + +// == HMAC TEST DATA ===================================================== +const HMACKEY1 = "a1020304050607080900b1020304050607080900c1020304050607080900d1020304050607080900e1020304050607080900f1020304050607080900a1020304"; // 64 bytes +// rfc9500testkey/aaa.txt.hs1.k1.sig +const SIGOSSHS1 = "1abc520eea206adec5cf8ea21119ddf19f488113"; +// rfc9500testkey/aaa.txt.hs256.k1.sig +const SIGOSSHS256 = "04fa8dada3a1793b767dcbdad7c9dde1826d10ab55c1743a2e02c39bac56d2c0"; +// rfc9500testkey/aaa.txt.hs384.k1.sig +const SIGOSSHS384 = "77223e196e2d541713f441134fa686cf415b4715d627613d03e507b66aff32778c5be1aea870fee74839fc141970c8a0"; +// rfc9500testkey/aaa.txt.hs512.k1.sig +const SIGOSSHS512 = "b39b8e2995ee35136bc874a95b8320cc1eca9f0d093ef12a2d6b72e796ed65589468ef4793bf77782c8be4e94042e8e676af91bda8d38dcab492046877e9890d"; + + + diff --git a/tsconfig.build.base.json b/tsconfig.build.base.json new file mode 100644 index 0000000..498f17b --- /dev/null +++ b/tsconfig.build.base.json @@ -0,0 +1,9 @@ +{ + "extends": ["./tsconfig.json"], + "compilerOptions": { + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "declarationMap": true + } +} diff --git a/tsconfig.build.cjs.json b/tsconfig.build.cjs.json new file mode 100644 index 0000000..7adfe4c --- /dev/null +++ b/tsconfig.build.cjs.json @@ -0,0 +1,9 @@ +{ + "extends": ["./tsconfig.build.base.json"], + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "classic", + "outDir": "./dist/require" + }, + "include": ["./src/index.cts"] +} diff --git a/tsconfig.build.esm.json b/tsconfig.build.esm.json new file mode 100644 index 0000000..b7e7f91 --- /dev/null +++ b/tsconfig.build.esm.json @@ -0,0 +1,8 @@ +{ + "extends": ["./tsconfig.build.base.json", "@tsconfig/node17/tsconfig.json"], + "compilerOptions": { + "outDir": "./dist/import/", + "lib": ["dom"] + }, + "include": ["./src/index.mts"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..dadde2f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "types": ["bun-types"], + + "lib": ["esnext"], + "module": "esnext", + "target": "esnext", + "moduleResolution": "bundler", + + "noEmit": true, + + "allowImportingTsExtensions": true, + "moduleDetection": "force", + + "strict": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + + }, + "include": ["./src"], + "exclude": ["./_work"] +} diff --git a/tsconfig.typedoc.json b/tsconfig.typedoc.json new file mode 100644 index 0000000..789266d --- /dev/null +++ b/tsconfig.typedoc.json @@ -0,0 +1,7 @@ +{ + "extends": ["./tsconfig.json", "@tsconfig/node17/tsconfig.json"], + "exclude": ["./_work", "./_src.bak/", "./src/*.test.mts"], + "compilerOptions": { + "lib": ["dom"] + } +} diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..f80dc7b --- /dev/null +++ b/typedoc.json @@ -0,0 +1,21 @@ +{ + "out": "./docs/", + "includes": "./src/", + "exclude": [ + "./src/__tests__/*", + "**/__tests__/**/*", + "**/__test_utils__/**/*", + "**/__fixtures__/**/*", + "**/testsuite/**/*", + "./src/*.test.ts" + ], + "excludeExternals": true, + "excludePrivate": true, + "navigationLinks": { + "Home": "https://kjur.github.io/typepki-webcrypto/", + "Issue": "https://github.com/kjur/typepki-webcrypto/issues", + "GitHub": "https://github.com/kjur/typepki-webcrypto", + "TypePKI": "https://kjur.github.io/typepki", + "jsrsasign": "https://kjur.github.io/jsrsasign" + } +}