k99 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.min.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
- function t(t){return(new TextEncoder).encode(t)}function e(t){return Symbol.asyncIterator in t||Symbol.iterator in t}async function n(r,o){if("string"==typeof o)return r.write(t(o));if("object"==typeof o){if(ArrayBuffer.isView(o))return r.write(new Uint8Array(o.buffer,o.byteOffset,o.byteLength));if(o instanceof ArrayBuffer)return r.write(new Uint8Array(o));if(e(o))for await(const t of o)t&&await n(r,t)}}function r(t,e){return"bigint"==typeof e?String(e):e}function o(o,s,i){const c=function(o,s){if(o instanceof ReadableStream)return[o,0,""];if(o instanceof URLSearchParams)return[o,0,""];if(o instanceof Blob)return[o,o.size,o.type];if(o instanceof FormData)return[o,0,""];if(ArrayBuffer.isView(o)||o instanceof ArrayBuffer)return[o,o.byteLength,""];if("string"==typeof o){const e=t(o);return[e,e.byteLength,""]}if("object"!=typeof o)return null;if(Array.isArray(o)||!e(o)){const e=t(JSON.stringify(o,r));return[e,e.byteLength,"application/json"]}const{writable:i,readable:c}=new TransformStream,u=i.getWriter();return s?.catch((t=>{i.abort(t||new DOMException("The user aborted a request.")).catch((()=>{}))})),(async()=>{for await(const t of o)t&&await n(u,t)})().then((()=>i.close()),(t=>i.abort(t))).catch((()=>{})),[c,0,""]}(o,i);if(!c)return null;const[u,a,f]=c;return f&&!s.get("Content-Type")&&s.set("Content-Type",f),a>0&&!s.get("Content-Length")&&s.set("Content-Length",String(a)),u}function s(t,e){t.delete("set-cookie");for(const{name:n,value:r,expire:o,domain:s,path:i,secure:c,httpOnly:u}of e)n&&t.append("set-cookie",[`${encodeURI(n)}=${encodeURI(r||"")}`,o&&`Expires=${o}`,s&&`Domain=${encodeURI(s)}`,i&&`Path=${encodeURI(i)}`,c&&"Secure",u&&"HttpOnly"].filter(Boolean).join("; "))}const i=new Set(["GET","OPTIONS"]);function c(t,e,n){n?t.set(e,n):t.delete(e)}function u(t,e,{runner:n,error:r,catch:u,method:a,environment:f}={}){return function t(l,p){const h=function(t,e){let n="";return"string"==typeof e?n=e:"function"==typeof e&&(n=e(t)),n&&"string"==typeof n||(n=t.method||"GET"),n.toUpperCase()}(l,a),y=new URL(l.url),{signal:d,headers:g}=l,m=function(t){return new Promise(((e,n)=>{if(t.aborted)return n(t.reason);t.addEventListener("abort",(()=>n(t.reason)),{once:!0})}))}(d),b=new Map,w=function(t){let e={};for(const n of t.replace(/\s/g,"").split(";")){const t=n.split("=");e[decodeURIComponent(t.shift())]=decodeURIComponent(t.join("="))}return e}(g.get("cookie")||""),O=[],T=new Headers,E=p?.root;let j=200,R=!1,S=null,A=()=>{},P=()=>{};const U=new Promise(((t,e)=>{A=t,P=e}));U.catch((()=>{}));let v={};const x={environment:f,parent:p,get error(){return S},get root(){return E||this},signal:d,url:y,fetch(e,{method:n="get",signal:r,body:s,headers:c}={}){const u=new URL(e,y),a=new Headers(c||{});if(!s||i.has(n.toUpperCase()))return t(new Request(u,{method:n,headers:a,signal:r}),x);const f=o(s,a);return t(new Request(u,{method:n,headers:a,signal:r,body:f}),x)},done(t,e){if(R)return null;const n=U.then(t,e);return n.catch(r),n},service(t,...e){if(t.rootOnly&&E)return E.service(t,...e);let n=b.get(t);if(!n){if(n=t(x),"function"!=typeof n)return;b.set(t,n)}return n(...e)},method:h,get params(){return v},requestHeaders:g,requestType:g.get("content-type")||"",referer:g.get("referer")||"",userAgent:g.get("user-agent")||"",accept:(g.get("accept")||"").split(/,\s*/).filter(Boolean),acceptLanguage:(g.get("accept-language")||"").split(/,\s*/).filter(Boolean),cookies:w,request:l,get destroyed(){return R},get status(){return j},set status(t){j=t},responseHeaders:T,get location(){return T.get("location")||""},set location(t){c(T,"location",t)},get responseType(){return T.get("content-type")||""},set responseType(t){c(T,"content-type",t)},getCookie:t=>function*(t,e){const n=t;for(const t of n)e&&t.name!==e||(yield{...t})}(O,t),setCookie(t,e,{expire:n,domain:r,path:o,secure:i,httpOnly:c}={}){O.push({name:t,value:e,expire:n,domain:r,path:o,secure:i,httpOnly:c}),s(T,O)},clearCookie(t,e){!function(t,e,n,r){let o="Fri, 31 Dec 1999 16:00:00 GMT";if("string"==typeof n){if(!n)return;const{domain:e,path:s,secure:i,httpOnly:c}=!0!==r&&r||{};t.push({name:n,value:"delete",expire:o,domain:e,path:s,secure:i,httpOnly:c})}else{const{domain:s,path:i,secure:c,httpOnly:u}=n||{};if(t.length=0,r)for(let n in e)t.push({name:n,value:"delete",expire:o,domain:s,path:i,secure:c,httpOnly:u})}}(O,w,t,e),s(T,O)}};function L(){return Promise.race([m,Promise.resolve().then((()=>e(x,(t=>{v=t}))))]).then((t=>t?Promise.race([m,t(x)]).then((t=>{if(t instanceof Response)return t;const e=new Headers(x.responseHeaders),{status:n}=x;if(!t)return new Response(null,{status:n,headers:e});const r=o(t,e,m);return new Response(r,{status:n,headers:e})})):null)).then((t=>(R=!0,A(),t)),(t=>(R=!0,S=t||!0,P(S),Promise.reject(t)))).catch(u)}return n?n(x,L):L()}(t)}function a(t,e){return n=>u(n,t,e)}async function f(t,e){for(const n of e){const e=await n(t);if(void 0!==e)return e}}function l(...t){return e=>f(e,t.flat())}function p(t,e,n){const r=function(n){return"function"==typeof e&&n.done((()=>e(n)),(t=>e(n,t))),(...e)=>t(n,...e)},{rootOnly:o}="object"==typeof e&&e||"object"==typeof n&&n||{};return Object.assign(r,{rootOnly:Boolean(o)}),r}function h(t,e,n,r){const o=function(r){const o=t(r)||{};return"function"==typeof e&&r.done((()=>e(o,r)),(t=>e(o,r,t))),"function"!=typeof n?()=>o:()=>(n(o,r),o)},{rootOnly:s}="object"==typeof e&&e||"object"==typeof n&&n||"object"==typeof r&&r||{};return Object.assign(o,{rootOnly:Boolean(s)}),o}function y(t,e,n){const r=function(n){let r;return"function"==typeof t&&n.done((()=>t(r,n)),(e=>t(r,n,e))),"function"!=typeof e?(...t)=>(t.length&&([r]=t),r):(...t)=>(t.length&&([r]=t,e(r,n)),r)},{rootOnly:o}="object"==typeof t&&t||"object"==typeof e&&e||"object"==typeof n&&n||{};return Object.assign(r,{rootOnly:Boolean(o)}),r}const d=t=>t;function g(t,e=d){return n=>{const r=e(n);return async e=>t(e,(async()=>r(e)))}}async function m(t,e,n,r,o){if(!(t instanceof w))return r(o),t;if(t.disabled)return null;const s=await async function(t,e,n,r){if(!t.size)return!0;n(r);for(const n of t){if(e.destroyed)return!1;const t=await n(Object.create(e,{params:{value:{...r}}}));if(!1===t)return!1;if("function"==typeof t)return t}return!0}(t.guards,n,r,o);if(!s)return null;if("function"==typeof s)return s;if(n.destroyed)return null;for await(const[s,i,c]of t.find(n.method,e,n)){if(n.destroyed)return null;const e=await m(s,c,n,r,{...o,...i});if(e)return t.__onionskin(e)}return null}function b(t){try{return decodeURIComponent(t)}catch{return t}}class w{disabled=!1;find(t,e,n){return[]}static make(t){return async(e,n)=>{const r=t.flat(),o=e.url.pathname.split("/").filter(Boolean).map(b);for(const t of r){const r=await m(t,o,e,n,{});if(r)return r}return null}}static create(t){return Object.defineProperties(new w,{find:{configurable:!0,value:t,writable:!0}})}guards=new Set;__onionskin=t=>t;onionskin(t){this.__onionskin=g(t,this.__onionskin)}}const O=/^:([a-zA-Z][a-zA-Z0-9]*)(?:\((.+)\))?([ius]+)?([?+*]?)$/;function T(t){const e=O.exec(t);if(!e)return t;const[,n,r=".*",o,s]=e;if(!r)return{name:n,pattern:new RegExp("^.*$",o),optional:"?"===s||"*"===s,many:"+"===s||"*"===s};let i=0,c=0;const u=["^(?:"];for(;i<r.length;){const e=r[i++];if(u.push(e),"\\"!==e)if(")"!==e)if("["!==e){if("("===e&&(c++,"?"===r[i]&&(i+=2,":"!==r[i-1])))return t}else for(;i<r.length;){const t=r[i++];if(u.push(t),"]"===t)break;"\\"===t&&u.push(r[i++])}else{if(0===c)return t;c--}else u.push(r[i++])}return c?t:(u.push(")$"),{name:n,pattern:new RegExp(u.join(""),o),optional:"?"===s||"*"===s,many:"+"===s||"*"===s})}function E(t,e){const n=[];if("string"==typeof t)for(const e of t.split("/"))e&&!/^\.+$/.test(e)&&n.push(T(e));else for(const[e,r]of function*([...t],[...e]){let n=(t.shift()||"").split("/"),r=[n.pop()||""];for(const t of n)yield[[t],[]];for(const n of t){const t=n.split("/");if(t.length<=1){r.push(n);continue}const o=e.splice(0,r.length);r.push(t.shift()||""),yield[r,o],r=[t.pop()||""];for(const e of t)yield[[e],[]]}yield[r,e]}(...t)){if(2===e.length&&!e[0]){const t=e[1];if(["","?","+","*"].includes(t)){const e=r[0];if("symbol"==typeof e){n.push({name:e,pattern:/^.*$/,optional:"?"===t||"*"===t,many:"+"===t||"*"===t});continue}if(e&&"object"==typeof e){const{name:r,pattern:o}=e;"symbol"==typeof r&&n.push({name:r,pattern:o instanceof RegExp?o:/^.*$/,optional:"?"===t||"*"===t,many:"+"===t||"*"===t})}}}const t=e.pop()||"",o=e.map(((t,e)=>[t,r[e]])).flat();o.push(t);const s=o.join("");s&&!/^\.+$/.test(s)&&n.push(T(s))}if(n.length)return t=>function(t,e,n){const r={};for(let n=0;n<t.length;n++){const o=t[n],s=e[n];if(o!==s){if("string"==typeof o)return;if(!s)return o.optional?[r,[]]:void 0;if(!o.pattern.test(s))return;r[o.name]=s}}if(!n)return[r,e.slice(t.length)];if(e.length<=t.length)return[r,[]];const o=t[t.length-1];if("string"!=typeof o&&(o.many||!(e.length>t.length))){for(let n=t.length;n<e.length;n++)if(!o.pattern.test(e[n]))return;return r[o.name]=e.slice(t.length-1),[r,[]]}}(n,t,e)}function j(t,e,n,r){const o={match:n,methods:e,handler:t=>f(t,r)};t.push(o);let s=!1;return()=>{if(s)return;s=!0;const e=t.indexOf(o);e<0||t.splice(e,1)}}const R=t=>"function"==typeof t;function S(t,e,n){const r=new Set(e);if(!n.length){const e=void 0;return(...n)=>j(t,r,e,n)}const[o]=n;if(o&&"object"==typeof o){const e=E([o,n.slice(1)],!0);return(...n)=>j(t,r,e,n)}const s=E("string"==typeof o?o:"",!0),i=n.filter(R);return i.length?j(t,r,s,i):(...e)=>j(t,r,s,e)}const A=new Set(["GET","POST","PUT","DELETE","HEAD","OPTIONS"]);function P(t){return A.has(t)}function U(t,e,n){const r=n instanceof w?n:"function"==typeof n?w.create(n):new v;return t.push({match:E(e,!1),router:r}),r}class v extends w{#t=[];route(...t){const[e]=t;if(e&&"object"==typeof e&&!(e instanceof w))return n=>U(this.#t,[e,t.slice(1)],n);const n="string"==typeof e?e:"",r="string"==typeof e?t[1]:e;return U(this.#t,n,r)}*find(t,e,n){for(const n of Array.from(this.#t)){if(!n.router&&!n.methods.has(t))continue;const{match:r}=n;if(!r){!n.router&&e.length||(yield[n.router||n.handler,{},e]);continue}if(!e.length)continue;const o=r(e);o&&(yield[n.router||n.handler,...o])}}verb(t,e,n){const r=function(t){return t?"string"==typeof t?[t.toUpperCase()].filter(P):Array.from(t).map((t=>"string"==typeof t&&t.toUpperCase())).filter(P):["GET","POST","PUT","DELETE"]}(t);return r.length?S(this.#t,r,[e,n]):()=>{}}match(...t){return S(this.#t,["GET","POST","PUT","DELETE"],t)}get(...t){return S(this.#t,["GET"],t)}post(...t){return S(this.#t,["POST"],t)}put(...t){return S(this.#t,["PUT"],t)}delete(...t){return S(this.#t,["DELETE"],t)}head(...t){return S(this.#t,["HEAD"],t)}options(...t){return S(this.#t,["OPTIONS"],t)}}function x(t,e){return async function(n,r){const o=new Request(n,r),{signal:s}=o;s.throwIfAborted();const i=await t(o);return i||("function"==typeof e?e(o):new Response(null,{status:404}))}}const L=()=>{};function k(...t){let e=L;for(const n of t.flat()){const t=e;e=async e=>n(e,(async()=>t(e)))}return e}class C{#e=Symbol();get name(){return this.#e}#n;get pattern(){return this.#n}constructor(t){this.#n=t}param(t){const e=t.params[this.#e];return Array.isArray(e)?e[0]??null:e??null}params(t){const e=t.params[this.#e];return"string"==typeof e?[e]:Array.isArray(e)?e:null}}export{v as ApiRouter,C as Param,w as Router,x as createFetch,u as main,a as make,l as merge,k as onionskin,g as packer,p as service,h as stateService,y as storeService};
6
+ function t(t){return(new TextEncoder).encode(t)}function e(t){return Symbol.asyncIterator in t||Symbol.iterator in t}async function n(r,o){if("string"==typeof o)return r.write(t(o));if("object"==typeof o){if(ArrayBuffer.isView(o))return r.write(new Uint8Array(o.buffer,o.byteOffset,o.byteLength));if(o instanceof ArrayBuffer)return r.write(new Uint8Array(o));if(e(o))for await(const t of o)t&&await n(r,t)}}function r(r,o,s,i){const c=function(r,o,s){if(r instanceof ReadableStream)return[r,0,""];if(r instanceof URLSearchParams)return[r,0,""];if(r instanceof Blob)return[r,r.size,r.type];if(r instanceof FormData)return[r,0,""];if(ArrayBuffer.isView(r)||r instanceof ArrayBuffer)return[r,r.byteLength,""];if("string"==typeof r){const e=t(r);return[e,e.byteLength,"text/plain"]}if(["bigint","boolean","number"].includes(typeof r)){const e=t(JSON.stringify(r,o));return[e,e.byteLength,"application/json"]}if("object"!=typeof r)return null;if(Array.isArray(r)||!e(r)){const e=t(JSON.stringify(r,o));return[e,e.byteLength,"application/json"]}const{writable:i,readable:c}=new TransformStream,u=i.getWriter();return s?.catch((t=>{i.abort(t||new DOMException("The user aborted a request.")).catch((()=>{}))})),(async()=>{for await(const t of r)t&&await n(u,t)})().then((()=>i.close()),(t=>i.abort(t))).catch((()=>{})),[c,0,""]}(r,s,i);if(!c)return null;const[u,a,f]=c;return f&&!o.get("Content-Type")&&o.set("Content-Type",f),a>0&&!o.get("Content-Length")&&o.set("Content-Length",String(a)),u}function o(t,e){t.delete("set-cookie");for(const{name:n,value:r,expire:o,domain:s,path:i,secure:c,httpOnly:u}of e)n&&t.append("set-cookie",[`${encodeURI(n)}=${encodeURI(r||"")}`,o&&`Expires=${o}`,s&&`Domain=${encodeURI(s)}`,i&&`Path=${encodeURI(i)}`,c&&"Secure",u&&"HttpOnly"].filter(Boolean).join("; "))}const s=new Set(["GET","OPTIONS"]);function i(t,e,n){n?t.set(e,n):t.delete(e)}function c(t,e){return"bigint"==typeof e?String(e):e}function u(t,e,{runner:n,error:u,catch:a,method:f,environment:l,replacer:p}={}){const h="function"==typeof p?p:c;return function t(c,p){const y=function(t,e){let n="";return"string"==typeof e?n=e:"function"==typeof e&&(n=e(t)),n&&"string"==typeof n||(n=t.method||"GET"),n.toUpperCase()}(c,f),d=new URL(c.url),{signal:g,headers:m}=c,b=function(t){return new Promise(((e,n)=>{if(t.aborted)return n(t.reason);t.addEventListener("abort",(()=>n(t.reason)),{once:!0})}))}(g),w=new Map,O=function(t){let e={};for(const n of t.replace(/\s/g,"").split(";")){const t=n.split("=");e[decodeURIComponent(t.shift())]=decodeURIComponent(t.join("="))}return e}(m.get("cookie")||""),T=[],E=new Headers,j=p?.root;let R=200,S=!1,A=null,P=()=>{},U=()=>{};const v=new Promise(((t,e)=>{P=t,U=e}));v.catch((()=>{}));let x={};const L={environment:l,parent:p,get error(){return A},get root(){return j||this},signal:g,url:d,fetch(e,{method:n="get",signal:o,body:i,headers:c}={}){const u=new URL(e,d),a=new Headers(c||{});if(!i||s.has(n.toUpperCase()))return t(new Request(u,{method:n,headers:a,signal:o}),L);const f=r(i,a,h);return t(new Request(u,{method:n,headers:a,signal:o,body:f}),L)},done(t,e){if(S)return null;const n=v.then(t,e);return n.catch(u),n},service(t,...e){if(t.rootOnly&&j)return j.service(t,...e);let n=w.get(t);if(!n){if(n=t(L),"function"!=typeof n)return;w.set(t,n)}return n(...e)},method:y,get params(){return x},requestHeaders:m,requestType:m.get("content-type")||"",referer:m.get("referer")||"",userAgent:m.get("user-agent")||"",accept:(m.get("accept")||"").split(/,\s*/).filter(Boolean),acceptLanguage:(m.get("accept-language")||"").split(/,\s*/).filter(Boolean),cookies:O,request:c,get destroyed(){return S},get status(){return R},set status(t){R=t},responseHeaders:E,get location(){return E.get("location")||""},set location(t){i(E,"location",t)},get responseType(){return E.get("content-type")||""},set responseType(t){i(E,"content-type",t)},getCookie:t=>function*(t,e){const n=t;for(const t of n)e&&t.name!==e||(yield{...t})}(T,t),setCookie(t,e,{expire:n,domain:r,path:s,secure:i,httpOnly:c}={}){T.push({name:t,value:e,expire:n,domain:r,path:s,secure:i,httpOnly:c}),o(E,T)},clearCookie(t,e){!function(t,e,n,r){let o="Fri, 31 Dec 1999 16:00:00 GMT";if("string"==typeof n){if(!n)return;const{domain:e,path:s,secure:i,httpOnly:c}=!0!==r&&r||{};t.push({name:n,value:"delete",expire:o,domain:e,path:s,secure:i,httpOnly:c})}else{const{domain:s,path:i,secure:c,httpOnly:u}=n||{};if(t.length=0,r)for(let n in e)t.push({name:n,value:"delete",expire:o,domain:s,path:i,secure:c,httpOnly:u})}}(T,O,t,e),o(E,T)}};function k(){return Promise.race([b,Promise.resolve().then((()=>e(L,(t=>{x=t}))))]).then((async t=>{const e=[t].flat().filter((t=>"function"==typeof t));if(!e.length)return null;let n;for(const t of e)if(n=await Promise.race([b,t(L)]),void 0!==n)break;if(n instanceof Response)return n;const o=new Headers(L.responseHeaders),{status:s}=L;if(!n)return new Response(null,{status:s,headers:o});const i=r(n,o,h,b);return new Response(i,{status:s,headers:o})})).then((t=>(S=!0,P(),t)),(t=>(S=!0,A=t||!0,U(A),Promise.reject(t)))).catch(a)}return n?n(L,k):k()}(t)}function a(t,e){return n=>u(n,t,e)}async function f(t,e){for(const n of e){const e=await n(t);if(void 0!==e)return e}}function l(...t){return e=>f(e,t.flat())}function p(t,e,n){const r=function(n){return"function"==typeof e&&n.done((()=>e(n)),(t=>e(n,t))),(...e)=>t(n,...e)},{rootOnly:o}="object"==typeof e&&e||"object"==typeof n&&n||{};return Object.assign(r,{rootOnly:Boolean(o)}),r}function h(t,e,n,r){const o=function(r){const o=t(r)||{};return"function"==typeof e&&r.done((()=>e(o,r)),(t=>e(o,r,t))),"function"!=typeof n?()=>o:()=>(n(o,r),o)},{rootOnly:s}="object"==typeof e&&e||"object"==typeof n&&n||"object"==typeof r&&r||{};return Object.assign(o,{rootOnly:Boolean(s)}),o}function y(t,e,n){const r=function(n){let r;return"function"==typeof t&&n.done((()=>t(r,n)),(e=>t(r,n,e))),"function"!=typeof e?(...t)=>(t.length&&([r]=t),r):(...t)=>(t.length&&([r]=t,e(r,n)),r)},{rootOnly:o}="object"==typeof t&&t||"object"==typeof e&&e||"object"==typeof n&&n||{};return Object.assign(r,{rootOnly:Boolean(o)}),r}const d=t=>t;function g(t,e=d){return n=>{const r=e(n);return async e=>t(e,(async()=>f(e,[r].flat())))}}function m(t){try{return decodeURIComponent(t)}catch{return t}}class b{disabled=!1;static async#t(t,e,n,r,o){if(!(t instanceof b))return r(o),[t].flat();if(t.disabled)return null;if(n.destroyed)return null;for await(const[s,i,c]of t.find(n.method,e,n)){if(n.destroyed)return null;const e=await b.#t(s,c,n,r,{...o,...i});if(e)return[t.#e,t.#n(e)].flat()}return null}find(t,e,n){return[]}static make(t){return async(e,n)=>{const r=t.flat(),o=e.url.pathname.split("/").filter(Boolean).map(m);for(const t of r){const r=await b.#t(t,o,e,n,{});if(r)return r}return null}}#e=[];guard(...t){const e=this.#e;for(const n of t.flat())"function"==typeof n&&e.push(n)}static create(t){return Object.defineProperties(new b,{find:{configurable:!0,value:t,writable:!0}})}#n=t=>t;onionskin(t){this.#n=g(t,this.#n)}}const w=/^:([a-zA-Z][a-zA-Z0-9]*)(?:\((.+)\))?([ius]+)?([?+*]?)$/;function O(t){const e=w.exec(t);if(!e)return t;const[,n,r=".*",o,s]=e;if(!r)return{name:n,pattern:new RegExp("^.*$",o),optional:"?"===s||"*"===s,many:"+"===s||"*"===s};let i=0,c=0;const u=["^(?:"];for(;i<r.length;){const e=r[i++];if(u.push(e),"\\"!==e)if(")"!==e)if("["!==e){if("("===e&&(c++,"?"===r[i]&&(i+=2,":"!==r[i-1])))return t}else for(;i<r.length;){const t=r[i++];if(u.push(t),"]"===t)break;"\\"===t&&u.push(r[i++])}else{if(0===c)return t;c--}else u.push(r[i++])}return c?t:(u.push(")$"),{name:n,pattern:new RegExp(u.join(""),o),optional:"?"===s||"*"===s,many:"+"===s||"*"===s})}function T(t,e){const n=[];if("string"==typeof t)for(const e of t.split("/"))e&&!/^\.+$/.test(e)&&n.push(O(e));else for(const[e,r]of function*([...t],[...e]){let n=(t.shift()||"").split("/"),r=[n.pop()||""];for(const t of n)yield[[t],[]];for(const n of t){const t=n.split("/");if(t.length<=1){r.push(n);continue}const o=e.splice(0,r.length);r.push(t.shift()||""),yield[r,o],r=[t.pop()||""];for(const e of t)yield[[e],[]]}yield[r,e]}(...t)){if(2===e.length&&!e[0]){const t=e[1];if(["","?","+","*"].includes(t)){const e=r[0];if("symbol"==typeof e){n.push({name:e,pattern:/^.*$/,optional:"?"===t||"*"===t,many:"+"===t||"*"===t});continue}if(e&&"object"==typeof e){const{name:r,pattern:o}=e;if("symbol"==typeof r){n.push({name:r,pattern:o instanceof RegExp?o:/^.*$/,optional:"?"===t||"*"===t,many:"+"===t||"*"===t});continue}}}}const t=e.pop()||"",o=e.map(((t,e)=>[t,r[e]])).flat();o.push(t);const s=o.join("");s&&!/^\.+$/.test(s)&&n.push(O(s))}if(n.length)return t=>function(t,e,n){const r={};for(let n=0;n<t.length;n++){const o=t[n],s=e[n];if(o!==s){if("string"==typeof o)return;if(!s)return o.optional?[r,[]]:void 0;if(!o.pattern.test(s))return;r[o.name]=s}}if(!n)return[r,e.slice(t.length)];if(e.length<=t.length)return[r,[]];const o=t[t.length-1];if("string"!=typeof o&&(o.many||!(e.length>t.length))){for(let n=t.length;n<e.length;n++)if(!o.pattern.test(e[n]))return;return r[o.name]=e.slice(t.length-1),[r,[]]}}(n,t,e)}function E(t,e,n,r){const o={match:n,methods:e,handlers:r};t.push(o);let s=!1;return()=>{if(s)return;s=!0;const e=t.indexOf(o);e<0||t.splice(e,1)}}const j=t=>"function"==typeof t;function R(t,e,n){const r=new Set(e);if(!n.length){const e=void 0;return(...n)=>E(t,r,e,n)}const[o]=n;if(o&&"object"==typeof o){const e=T([o,n.slice(1)],!0);return(...n)=>E(t,r,e,n)}const s=T("string"==typeof o?o:"",!0),i=n.filter(j);return i.length?E(t,r,s,i):(...e)=>E(t,r,s,e)}const S=new Set(["GET","POST","PUT","DELETE","HEAD","OPTIONS"]);function A(t){return S.has(t)}function P(t,e,n){const r=n instanceof b?n:"function"==typeof n?b.create(n):new U;return t.push({match:T(e,!1),router:r}),r}class U extends b{#r=[];route(...t){const[e]=t;if(e&&"object"==typeof e&&!(e instanceof b))return n=>P(this.#r,[e,t.slice(1)],n);const n="string"==typeof e?e:"",r="string"==typeof e?t[1]:e;return P(this.#r,n,r)}*find(t,e,n){for(const n of Array.from(this.#r)){if(!n.router&&!n.methods.has(t))continue;const{match:r}=n;if(!r){!n.router&&e.length||(yield[n.router||n.handlers,{},e]);continue}if(!e.length)continue;const o=r(e);o&&(yield[n.router||n.handlers,...o])}}verb(t,e,...n){const r=function(t){return t?"string"==typeof t?[t.toUpperCase()].filter(A):Array.from(t).map((t=>"string"==typeof t&&t.toUpperCase())).filter(A):["GET","POST","PUT","DELETE"]}(t);return r.length?R(this.#r,r,[e,...n]):()=>{}}match(...t){return R(this.#r,["GET","POST","PUT","DELETE"],t)}get(...t){return R(this.#r,["GET"],t)}post(...t){return R(this.#r,["POST"],t)}put(...t){return R(this.#r,["PUT"],t)}delete(...t){return R(this.#r,["DELETE"],t)}head(...t){return R(this.#r,["HEAD"],t)}options(...t){return R(this.#r,["OPTIONS"],t)}}function v(t,e){return async function(n,r){const o=new Request(n,r),{signal:s}=o;s.throwIfAborted();const i=await t(o);return i||("function"==typeof e?e(o):new Response(null,{status:404}))}}const x=()=>{};function L(...t){let e=x;for(const n of t.flat()){const t=e;e=async e=>n(e,(async()=>t(e)))}return e}class k{#o=Symbol();get name(){return this.#o}#s;get pattern(){return this.#s}constructor(t){this.#s=t}param(t){const e=t.params[this.#o];return Array.isArray(e)?e[0]??null:e??null}params(t){const e=t.params[this.#o];return"string"==typeof e?[e]:Array.isArray(e)?e:null}}export{U as ApiRouter,k as Param,b as Router,v as createFetch,u as main,a as make,l as merge,L as onionskin,g as packer,p as service,h as stateService,y as storeService};
package/index.mjs CHANGED
@@ -1,14 +1,15 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  /**
7
7
  *
8
8
  * @param {string} str
9
- * @returns {Uint8Array}
9
+ * @returns {Uint8Array<ArrayBuffer>}
10
10
  */
11
11
  function str2utf8bin(str) {
12
+ // @ts-ignore
12
13
  return new TextEncoder().encode(str);
13
14
  }
14
15
  /**
@@ -47,26 +48,15 @@ async function write(writer, chunk) {
47
48
  }
48
49
  }
49
50
 
50
- /**
51
- *
52
- * @param {any} k
53
- * @param {any} v
54
- * @returns {any}
55
- */
56
- function replacer(k, v) {
57
- if (typeof v === 'bigint') {
58
- return String(v);
59
- }
60
- return v;
61
- }
62
51
 
63
52
  /**
64
53
  *
65
54
  * @param {any} result
55
+ * @param {(this: any, key: string, value: any) => any} replacer
66
56
  * @param {Promise<never>} [aborted]
67
57
  * @returns {[BodyInit, number, string] | null}
68
58
  */
69
- function toBodyData(result, aborted) {
59
+ function toBodyData(result, replacer, aborted) {
70
60
  if (result instanceof ReadableStream) {
71
61
  return [result, 0, ''];
72
62
  }
@@ -80,11 +70,16 @@ function toBodyData(result, aborted) {
80
70
  return [result, 0, ''];
81
71
  }
82
72
  if (ArrayBuffer.isView(result) || result instanceof ArrayBuffer) {
73
+ // @ts-ignore
83
74
  return [result, result.byteLength, ''];
84
75
  }
85
76
  if (typeof result === 'string') {
86
77
  const body = str2utf8bin(result);
87
- return [body, body.byteLength, ''];
78
+ return [body, body.byteLength, 'text/plain'];
79
+ }
80
+ if (['bigint', 'boolean', 'number'].includes(typeof result)) {
81
+ const body = str2utf8bin(JSON.stringify(result, replacer));
82
+ return [body, body.byteLength, 'application/json'];
88
83
  }
89
84
  if (typeof result !== 'object') {
90
85
  return null;
@@ -111,11 +106,12 @@ function toBodyData(result, aborted) {
111
106
  *
112
107
  * @param {any} result
113
108
  * @param {Headers} headers
109
+ * @param {(this: any, key: string, value: any) => any} replacer
114
110
  * @param {Promise<never>} [aborted]
115
111
  * @returns
116
112
  */
117
- function toBody(result, headers, aborted) {
118
- const bodyData = toBodyData(result, aborted);
113
+ function toBody(result, headers, replacer, aborted) {
114
+ const bodyData = toBodyData(result, replacer, aborted);
119
115
  if (!bodyData) { return null; }
120
116
  const [body, size, type] = bodyData;
121
117
  if (type && !headers.get('Content-Type')) {
@@ -209,7 +205,7 @@ function clearCookie(
209
205
  }
210
206
  }
211
207
 
212
- /** @import { Context, Cookie, CookieOption, FindHandler, Method, Options, Params, Service } from './types' */
208
+ /** @import { Context, Cookie, CookieOption, FindHandler, HandlerResult, Method, Options, Params, Service } from './types' */
213
209
 
214
210
 
215
211
  const noBodyMethods = new Set(['GET', 'OPTIONS']);
@@ -262,6 +258,18 @@ function getMethod(request, toMethod) {
262
258
  }
263
259
  return /** @type {Method} */(methodStr.toUpperCase());
264
260
  }
261
+ /**
262
+ *
263
+ * @param {any} k
264
+ * @param {any} v
265
+ * @returns {any}
266
+ */
267
+ function defaultReplacer(k, v) {
268
+ if (typeof v === 'bigint') {
269
+ return String(v);
270
+ }
271
+ return v;
272
+ }
265
273
  /**
266
274
  *
267
275
  * @param {Request} request
@@ -269,10 +277,15 @@ function getMethod(request, toMethod) {
269
277
  * @param {Options} [options]
270
278
  * @returns {Promise<Response | null>}
271
279
  */
272
- function main(
273
- request, getHandler,
274
- { runner, error: echoError, catch: catchError, method: toMethod, environment } = {},
275
- ) {
280
+ function main(request, getHandler, {
281
+ runner,
282
+ error: echoError,
283
+ catch: catchError,
284
+ method: toMethod,
285
+ environment,
286
+ replacer: JSONReplacer,
287
+ } = {}) {
288
+ const replacer = typeof JSONReplacer === 'function' ? JSONReplacer : defaultReplacer;
276
289
  /**
277
290
  *
278
291
  * @param {Request} request
@@ -296,12 +309,12 @@ function main(
296
309
  /** @type {any} */
297
310
  let error = null;
298
311
 
299
- let resolve = () => {};
312
+ let resolve = () => { };
300
313
  /** @type {(error: unknown) => void} */
301
- let reject = () => {};
314
+ let reject = () => { };
302
315
  /** @type {Promise<void>} */
303
316
  const donePromise = new Promise((a, b) => { resolve = a; reject = b; });
304
- donePromise.catch(() => {});
317
+ donePromise.catch(() => { });
305
318
 
306
319
  /** @type {Params} */
307
320
  let params = {};
@@ -319,7 +332,7 @@ function main(
319
332
  if (!data || noBodyMethods.has(method.toUpperCase())) {
320
333
  return exec(new Request(fetchUrl, { method, headers, signal }), context);
321
334
  }
322
- const body = toBody(data, headers);
335
+ const body = toBody(data, headers, replacer);
323
336
  return exec(new Request(fetchUrl, { method, headers, signal, body }), context);
324
337
  },
325
338
  done(onfulfilled, onrejected) {
@@ -364,7 +377,7 @@ function main(
364
377
  set responseType(type) { setHeader(responseHeaders, 'content-type', type); },
365
378
  getCookie(name) { return getCookie(sentCookies, name); },
366
379
  setCookie(name, value, { expire, domain, path, secure, httpOnly } = {}) {
367
- sentCookies.push({name, value, expire, domain, path, secure, httpOnly});
380
+ sentCookies.push({ name, value, expire, domain, path, secure, httpOnly });
368
381
  setCookiesHeader(responseHeaders, sentCookies);
369
382
  },
370
383
  /**
@@ -382,16 +395,22 @@ function main(
382
395
  return Promise.race([
383
396
  aborted,
384
397
  Promise.resolve().then(() => getHandler(context, v => { params = v; })),
385
- ]).then(handler => handler ? Promise.race([aborted, handler(context)]).then(result => {
386
- if (result instanceof Response) {
387
- return result;
398
+ ]).then(async handlers => {
399
+ const allHandlers = [handlers].flat().filter(h => typeof h === 'function');
400
+ if (!allHandlers.length) { return null; }
401
+ /** @type {HandlerResult?} */
402
+ let result;
403
+ for (const handle of allHandlers) {
404
+ result = await Promise.race([aborted, handle(context)]);
405
+ if (result !== undefined) { break; }
388
406
  }
407
+ if (result instanceof Response) { return result; }
389
408
  const headers = new Headers(context.responseHeaders);
390
409
  const { status } = context;
391
410
  if (!result) { return new Response(null, { status, headers }); }
392
- const body = toBody(result, headers, aborted);
411
+ const body = toBody(result, headers, replacer, aborted);
393
412
  return new Response(body, { status, headers });
394
- }) : null).then(response => {
413
+ }).then(response => {
395
414
  destroyed = true;
396
415
  resolve();
397
416
  return response;
@@ -419,12 +438,12 @@ function make(getHandler, options) {
419
438
  return r => main(r, getHandler, options);
420
439
  }
421
440
 
422
- /** @import { Context, Handler } from './main/types' */
441
+ /** @import { Context, Handler, HandlerResult } from './main/types' */
423
442
  /**
424
443
  *
425
444
  * @param {Context} context
426
445
  * @param {Handler[]} handlers
427
- * @returns {Promise<string | boolean | object | undefined>}
446
+ * @returns {Promise<HandlerResult>}
428
447
  */
429
448
  async function runHandles(context, handlers) {
430
449
  for (const handle of handlers) {
@@ -626,9 +645,11 @@ function storeService(destroy, exec, options) {
626
645
  /** @import { Onionskin } from './onionskin.mjs' */
627
646
  /**
628
647
  * @callback Packer
629
- * @param {Handler} handler
630
- * @returns {Handler}
648
+ * @param {Handler | Handler[]} handler
649
+ * @returns {Handler | Handler[]}
631
650
  */
651
+
652
+
632
653
  /** @type {Packer} */
633
654
  const noop$1 = h => h;
634
655
  /**
@@ -640,7 +661,7 @@ const noop$1 = h => h;
640
661
  function packer(onionskin, packer = noop$1) {
641
662
  return h => {
642
663
  const handler = packer(h);
643
- return async (ctx) => onionskin(ctx, async () => handler(ctx));
664
+ return async (ctx) => onionskin(ctx, async () => runHandles(ctx, [handler].flat()));
644
665
  };
645
666
  }
646
667
 
@@ -653,7 +674,7 @@ function packer(onionskin, packer = noop$1) {
653
674
  * @returns {PromiseLike<boolean | Handler | void> | boolean | Handler | void}
654
675
  */
655
676
  /**
656
- * @typedef {[Handler | Router, Record<string | symbol, any>, string[]]} FindItem
677
+ * @typedef {[Handler | Handler[] | Router, Record<string | symbol, any>, string[]]} FindItem
657
678
  */
658
679
  /**
659
680
  * @callback Finder
@@ -664,55 +685,6 @@ function packer(onionskin, packer = noop$1) {
664
685
  * @returns {AsyncIterable<FindItem> | Iterable<FindItem>}
665
686
  */
666
687
 
667
- /**
668
- *
669
- * @param {Set<Guard>} guards
670
- * @param {Context} ctx
671
- * @param {(v: any) => void} setParams
672
- * @param {object} params
673
- * @returns {Promise<boolean | Handler>}
674
- */
675
- async function execGuard(guards, ctx, setParams, params) {
676
- if (!guards.size) { return true; }
677
- setParams(params);
678
- for (const guard of guards) {
679
- if (ctx.destroyed) { return false; }
680
- const ret = await guard(Object.create(ctx, {
681
- params: { value: { ...params } },
682
- }));
683
- if (ret === false) { return false; }
684
- // @ts-ignore
685
- if (typeof ret === 'function') { return ret; }
686
- }
687
- return true;
688
- }
689
-
690
- /**
691
- *
692
- * @param {Router | Handler} route
693
- * @param {string[]} path
694
- * @param {Context} ctx
695
- * @param {(v: Params) => void} setParams
696
- * @param {Params} params
697
- * @returns {Promise<Handler | null>}
698
- */
699
- async function find(route, path, ctx, setParams, params) {
700
- if (!(route instanceof Router)) {
701
- setParams(params);
702
- return route;
703
- }
704
- if (route.disabled) { return null; }
705
- const guardResult = await execGuard(route.guards, ctx, setParams, params);
706
- if (!guardResult) { return null; }
707
- if (typeof guardResult === 'function') { return guardResult; }
708
- if (ctx.destroyed) { return null; }
709
- for await (const [r, result, p] of route.find(ctx.method, path, ctx)) {
710
- if (ctx.destroyed) { return null; }
711
- const res = await find(r, p, ctx, setParams, { ...params, ...result });
712
- if (res) { return route.__onionskin(res); }
713
- }
714
- return null;
715
- }
716
688
 
717
689
  /**
718
690
  *
@@ -731,6 +703,29 @@ function uriDecode(t) {
731
703
  */
732
704
  class Router {
733
705
  disabled = false;
706
+ /**
707
+ *
708
+ * @param {Router | Handler[] | Handler} route
709
+ * @param {string[]} path
710
+ * @param {Context} ctx
711
+ * @param {(v: Params) => void} setParams
712
+ * @param {Params} params
713
+ * @returns {Promise<Handler[] | null>}
714
+ */
715
+ static async #find(route, path, ctx, setParams, params) {
716
+ if (!(route instanceof Router)) {
717
+ setParams(params);
718
+ return [route].flat();
719
+ }
720
+ if (route.disabled) { return null; }
721
+ if (ctx.destroyed) { return null; }
722
+ for await (const [r, result, p] of route.find(ctx.method, path, ctx)) {
723
+ if (ctx.destroyed) { return null; }
724
+ const res = await Router.#find(r, p, ctx, setParams, { ...params, ...result });
725
+ if (res) { return [route.#guards, route.#onionskin(res)].flat(); }
726
+ }
727
+ return null;
728
+ }
734
729
  /**
735
730
  * @abstract
736
731
  * @param {Method} method
@@ -749,13 +744,28 @@ class Router {
749
744
  const list = routers.flat();
750
745
  const path = ctx.url.pathname.split('/').filter(Boolean).map(uriDecode);
751
746
  for (const route of list) {
752
- const res = await find(route, path, ctx, setParams, {});
747
+ const res = await Router.#find(route, path, ctx, setParams, {});
753
748
  if (res) { return res; }
754
749
  }
755
750
  return null;
756
751
  };
757
752
  }
758
753
 
754
+
755
+ /** @type {Handler[]} */
756
+ #guards = [];
757
+ /**
758
+ *
759
+ * @param {...Handler | Handler[]} guards
760
+ */
761
+ guard(...guards) {
762
+ const list =this.#guards;
763
+ for (const guard of guards.flat()) {
764
+ if (typeof guard !== 'function') { continue; }
765
+ list.push(guard);
766
+ }
767
+ }
768
+
759
769
  /**
760
770
  *
761
771
  * @param {Finder} find
@@ -766,16 +776,14 @@ class Router {
766
776
  'find': { configurable: true, value: find, writable: true },
767
777
  });
768
778
  }
769
- /** @readonly @type {Set<Guard>} */
770
- guards = new Set();
771
779
  /**
772
780
  *
773
- * @param {Handler} h
774
- * @returns {Handler}
781
+ * @param {Handler | Handler[]} h
782
+ * @returns {Handler | Handler[]}
775
783
  */
776
- __onionskin = (h) => h;
784
+ #onionskin = (h) => h;
777
785
  /** @param {Onionskin} os */
778
- onionskin(os) { this.__onionskin = packer(os, this.__onionskin); }
786
+ onionskin(os) { this.#onionskin = packer(os, this.#onionskin); }
779
787
  }
780
788
 
781
789
  /** @import { Match } from './index.mjs' */
@@ -941,6 +949,7 @@ function toMatch(path, end) {
941
949
  optional: modifier === '?' || modifier === '*',
942
950
  many: modifier === '+' || modifier === '*',
943
951
  });
952
+ continue;
944
953
  }
945
954
  }
946
955
  }
@@ -972,7 +981,7 @@ function toMatch(path, end) {
972
981
  */
973
982
  function bind(routes, methods, match, handlers) {
974
983
  /** @type {Route} */
975
- const route = { match, methods, handler: ctx => runHandles(ctx, handlers) };
984
+ const route = { match, methods, handlers: handlers };
976
985
  routes.push(route);
977
986
  let removed = false;
978
987
  return () => {
@@ -1054,8 +1063,7 @@ function getMethods(methods) {
1054
1063
  * @typedef {object} Route
1055
1064
  * @property {Match} [match] 路径匹配
1056
1065
  * @property {null} [router]
1057
- * @property {string} [plugin] 所属插件
1058
- * @property {Handler} handler 处理函数
1066
+ * @property {Handler[]} handlers 处理函数
1059
1067
  * @property {Set<Method>} methods 方法列表
1060
1068
  */
1061
1069
 
@@ -1142,14 +1150,14 @@ class ApiRouter extends Router {
1142
1150
  const {match} = route;
1143
1151
  if (!match) {
1144
1152
  if (route.router || !path.length) {
1145
- yield [route.router || route.handler, {}, path];
1153
+ yield [route.router || route.handlers, {}, path];
1146
1154
  }
1147
1155
  continue;
1148
1156
  }
1149
1157
  if (!path.length) { continue; }
1150
1158
  const result = match(path);
1151
1159
  if (!result) { continue; }
1152
- yield [route.router || route.handler, ...result];
1160
+ yield [route.router || route.handlers, ...result];
1153
1161
  }
1154
1162
  }
1155
1163
  /**
@@ -1177,25 +1185,25 @@ class ApiRouter extends Router {
1177
1185
  /**
1178
1186
  * @param {Method | Iterable<Method> | ArrayLike<Method>} methods
1179
1187
  * @param {string| Handler} [path]
1180
- * @param {Handler} [handler]
1188
+ * @param {...Handler} handler
1181
1189
  * @returns {Binder | (() => void)}
1182
1190
  */
1183
- verb(methods, path, handler) {
1191
+ verb(methods, path, ...handler) {
1184
1192
  const allMethods = getMethods(methods);
1185
1193
  if (!allMethods.length) { return () => {}; }
1186
- return verb(this.#routes, allMethods, [path, handler]);
1194
+ return verb(this.#routes, allMethods, [path, ...handler]);
1187
1195
  }
1188
1196
  /**
1189
1197
  * 注册 HTTP GET/POST/PUT/DELETE 处理函数
1190
1198
  * @overload
1191
- * @param {Handler} handler 要注册的处理函数
1199
+ * @param {...Handler} handlers 要注册的处理函数
1192
1200
  * @returns {() => void}
1193
1201
  */
1194
1202
  /**
1195
1203
  * 注册处理函数
1196
1204
  * @overload
1197
1205
  * @param {string} path 要注册的路径
1198
- * @param {Handler} handler 要注册的处理函数
1206
+ * @param {...Handler} handlers 要注册的处理函数
1199
1207
  * @returns {() => void}
1200
1208
  */
1201
1209
  /**
@@ -1221,14 +1229,14 @@ class ApiRouter extends Router {
1221
1229
  /**
1222
1230
  * 注册 HTTP GET 处理函数
1223
1231
  * @overload
1224
- * @param {Handler} handler 要注册的处理函数
1232
+ * @param {...Handler} handlers 要注册的处理函数
1225
1233
  * @returns {() => void}
1226
1234
  */
1227
1235
  /**
1228
1236
  * 注册 HTTP GET 处理函数
1229
1237
  * @overload
1230
1238
  * @param {string} path 要注册的路径
1231
- * @param {Handler} handler 要注册的处理函数
1239
+ * @param {...Handler} handlers 要注册的处理函数
1232
1240
  * @returns {() => void}
1233
1241
  */
1234
1242
  /**
@@ -1252,14 +1260,14 @@ class ApiRouter extends Router {
1252
1260
  /**
1253
1261
  * 注册 HTTP POST 处理函数
1254
1262
  * @overload
1255
- * @param {Handler} handler 要注册的处理函数
1263
+ * @param {...Handler} handlers 要注册的处理函数
1256
1264
  * @returns {() => void}
1257
1265
  */
1258
1266
  /**
1259
1267
  * 注册 HTTP POST 处理函数
1260
1268
  * @overload
1261
1269
  * @param {string} path 要注册的路径
1262
- * @param {Handler} handler 要注册的处理函数
1270
+ * @param {...Handler} handlers 要注册的处理函数
1263
1271
  * @returns {() => void}
1264
1272
  */
1265
1273
  /**
@@ -1283,14 +1291,14 @@ class ApiRouter extends Router {
1283
1291
  /**
1284
1292
  * 注册 HTTP PUT 处理函数
1285
1293
  * @overload
1286
- * @param {Handler} handler 要注册的处理函数
1294
+ * @param {...Handler} handlers 要注册的处理函数
1287
1295
  * @returns {() => void}
1288
1296
  */
1289
1297
  /**
1290
1298
  * 注册 HTTP PUT 处理函数
1291
1299
  * @overload
1292
1300
  * @param {string} path 要注册的路径
1293
- * @param {Handler} handler 要注册的处理函数
1301
+ * @param {...Handler} handlers 要注册的处理函数
1294
1302
  * @returns {() => void}
1295
1303
  */
1296
1304
  /**
@@ -1314,14 +1322,14 @@ class ApiRouter extends Router {
1314
1322
  /**
1315
1323
  * 注册 HTTP DELETE 处理函数
1316
1324
  * @overload
1317
- * @param {Handler} handler 要注册的处理函数
1325
+ * @param {...Handler} handlers 要注册的处理函数
1318
1326
  * @returns {() => void}
1319
1327
  */
1320
1328
  /**
1321
1329
  * 注册 HTTP DELETE 处理函数
1322
1330
  * @overload
1323
1331
  * @param {string} path 要注册的路径
1324
- * @param {Handler} handler 要注册的处理函数
1332
+ * @param {...Handler} handlers 要注册的处理函数
1325
1333
  * @returns {() => void}
1326
1334
  */
1327
1335
  /**
@@ -1345,14 +1353,14 @@ class ApiRouter extends Router {
1345
1353
  /**
1346
1354
  * 注册 HTTP HEAD 处理函数
1347
1355
  * @overload
1348
- * @param {Handler} handler 要注册的处理函数
1356
+ * @param {...Handler} handlers 要注册的处理函数
1349
1357
  * @returns {() => void}
1350
1358
  */
1351
1359
  /**
1352
1360
  * 注册 HTTP HEAD 处理函数
1353
1361
  * @overload
1354
1362
  * @param {string} path 要注册的路径
1355
- * @param {Handler} handler 要注册的处理函数
1363
+ * @param {...Handler} handlers 要注册的处理函数
1356
1364
  * @returns {() => void}
1357
1365
  */
1358
1366
  /**
@@ -1376,14 +1384,14 @@ class ApiRouter extends Router {
1376
1384
  /**
1377
1385
  * 注册 HTTP OPTIONS 处理函数
1378
1386
  * @overload
1379
- * @param {Handler} handler 要注册的处理函数
1387
+ * @param {...Handler} handlers 要注册的处理函数
1380
1388
  * @returns {() => void}
1381
1389
  */
1382
1390
  /**
1383
1391
  * 注册 HTTP OPTIONS 处理函数
1384
1392
  * @overload
1385
1393
  * @param {string} path 要注册的路径
1386
- * @param {Handler} handler 要注册的处理函数
1394
+ * @param {...Handler} handlers 要注册的处理函数
1387
1395
  * @returns {() => void}
1388
1396
  */
1389
1397
  /**
@@ -1461,7 +1469,7 @@ class Param {
1461
1469
  get pattern() { return this.#pattern; }
1462
1470
  /**
1463
1471
  *
1464
- * @param {RegExp} pattern
1472
+ * @param {RegExp?} [pattern]
1465
1473
  */
1466
1474
  constructor(pattern) {
1467
1475
  this.#pattern = pattern;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "k99",
3
3
  "description": "前后端均可用的 web 服务器",
4
- "version": "0.7.0",
4
+ "version": "0.8.0",
5
5
  "dependencies": {},
6
6
  "keywords": [
7
7
  "k99",
package/services.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  'use strict';
package/services.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  import { Service } from 'k99';
package/services.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  (function (global, factory) {
package/services.min.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).k99Services={})}(this,(function(e){"use strict";function n(e){const n=e.indexOf("=");return n<0?[decodeURIComponent(e),""]:[decodeURIComponent(e.substring(0,n)),decodeURIComponent(e.substring(n+1))]}async function t(e){try{const t=await e.text();return t.length?function(e){const t={};for(const o of e.split("&").filter(Boolean)){const[e,r]=n(o);t[e]=e in t?[t[e],r].flat():[r]}return t}(t):null}catch{}return null}e.formBodyService=function(e){const[n,o]=e.requestType.replace(/\s/g,"").split(";");if("application/x-www-form-urlencoded"!==n)return()=>null;if(o&&"charset=UTF-8"!==o)return()=>null;const{request:r}=e;if(r.bodyUsed)return()=>null;const s=t(r);return()=>s},e.jsonBodyService=function(e){const[n,t]=e.requestType.replace(/\s/g,"").split(";");if("application/json"!==n&&"text/json"!==n)return()=>null;if(t&&"charset=UTF-8"!==t)return()=>null;const{request:o}=e;if(o.bodyUsed)return()=>null;const r=o.json();return()=>r}}));
package/services.min.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
- * k99 v0.7.0
3
- * (c) 2019-2025 猛火Fierflame
2
+ * k99 v0.8.0
3
+ * (c) 2019-2026 猛火Fierflame
4
4
  * @license MIT
5
5
  */
6
6
  function n(n){const t=n.indexOf("=");return t<0?[decodeURIComponent(n),""]:[decodeURIComponent(n.substring(0,t)),decodeURIComponent(n.substring(t+1))]}async function t(t){try{const e=await t.text();return e.length?function(t){const e={};for(const o of t.split("&").filter(Boolean)){const[t,r]=n(o);e[t]=t in e?[e[t],r].flat():[r]}return e}(e):null}catch{}return null}const e=function(n){const[e,o]=n.requestType.replace(/\s/g,"").split(";");if("application/x-www-form-urlencoded"!==e)return()=>null;if(o&&"charset=UTF-8"!==o)return()=>null;const{request:r}=n;if(r.bodyUsed)return()=>null;const s=t(r);return()=>s},o=function(n){const[t,e]=n.requestType.replace(/\s/g,"").split(";");if("application/json"!==t&&"text/json"!==t)return()=>null;if(e&&"charset=UTF-8"!==e)return()=>null;const{request:o}=n;if(o.bodyUsed)return()=>null;const r=o.json();return()=>r};export{e as formBodyService,o as jsonBodyService};