diff --git a/dist/browser.js b/dist/browser.js index eb0ffec..c038f48 100644 --- a/dist/browser.js +++ b/dist/browser.js @@ -107,12 +107,7 @@ } const metrofetch = async function browserFetch(req2) { if (req2[Symbol.metroProxy]) { - if (req2.body && req2.body[Symbol.metroSource]) { - let body = req2.body[Symbol.metroSource]; - req2 = new Request(req2[Symbol.metroSource], { body }); - } else { - req2 = req2[Symbol.metroSource]; - } + req2 = req2[Symbol.metroSource]; } const res = await fetch(req2); return response(res); @@ -149,103 +144,6 @@ function client(...options) { return new Client(...options); } - function bodyProxy(body, r) { - let source = r.body; - if (!source) { - if (body === null) { - source = new ReadableStream(); - } else if (body instanceof ReadableStream) { - source = body; - } else if (body instanceof Blob) { - source = body.stream(); - } else { - source = new ReadableStream({ - start(controller) { - let chunk; - switch (typeof body) { - case "object": - if (typeof body.toString == "function") { - chunk = body.toString(); - } else if (body instanceof FormData) { - chunk = new URLSearchParams(body).toString(); - } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) { - chunk = body; - } else { - throw metroError("Cannot convert body to ReadableStream", body); - } - break; - case "string": - case "number": - case "boolean": - chunk = body; - break; - default: - throw metroError("Cannot convert body to ReadableStream", body); - break; - } - controller.enqueue(chunk); - controller.close(); - } - }); - } - } - return new Proxy(source, { - get(target, prop, receiver) { - switch (prop) { - case Symbol.metroProxy: - return true; - break; - case Symbol.metroSource: - return body; - break; - case "toString": - return function() { - return "" + body; - }; - break; - } - if (body && typeof body == "object") { - if (prop in body) { - if (typeof body[prop] == "function") { - return function(...args) { - return body[prop].apply(body, args); - }; - } - return body[prop]; - } - } - if (prop in target && prop != "toString") { - if (typeof target[prop] == "function") { - return function(...args) { - return target[prop].apply(target, args); - }; - } - return target[prop]; - } - }, - has(target, prop) { - if (body && typeof body == "object") { - return prop in body; - } else { - return prop in target; - } - }, - ownKeys(target) { - if (body && typeof body == "object") { - return Reflect.ownKeys(body); - } else { - return Reflect.ownKeys(target); - } - }, - getOwnPropertyDescriptor(target, prop) { - if (body && typeof body == "object") { - return Object.getOwnPropertyDescriptor(body, prop); - } else { - return Object.getOwnPropertyDescriptor(target, prop); - } - } - }); - } function getRequestParams(req, current) { let params = current || {}; if (!params.url && current.url) { @@ -275,7 +173,7 @@ value = value[Symbol.metroSource]; } if (typeof value == "function") { - value(params[prop], params); + params[prop] = value(params[prop], params); } else { if (prop == "url") { params.url = url(params.url, value); @@ -292,6 +190,9 @@ } } } + if (req instanceof Request && req.data) { + params.body = req.data; + } return params; } function request(...options) { @@ -309,10 +210,10 @@ Object.assign(requestParams, getRequestParams(option, requestParams)); } } - let body = requestParams.body; - if (body) { - if (typeof body == "object" && !(body instanceof String) && !(body instanceof ReadableStream) && !(body instanceof Blob) && !(body instanceof ArrayBuffer) && !(body instanceof DataView) && !(body instanceof FormData) && !(body instanceof URLSearchParams) && (typeof TypedArray == "undefined" || !(body instanceof TypedArray))) { - requestParams.body = JSON.stringify(body); + let data = requestParams.body; + if (data) { + if (typeof data == "object" && !(data instanceof String) && !(data instanceof ReadableStream) && !(data instanceof Blob) && !(data instanceof ArrayBuffer) && !(data instanceof DataView) && !(data instanceof FormData) && !(data instanceof URLSearchParams) && (typeof TypedArray == "undefined" || !(data instanceof TypedArray))) { + requestParams.body = JSON.stringify(data); } } let r = new Request(requestParams.url, requestParams); @@ -328,25 +229,21 @@ break; case "with": return function(...options2) { - if (body) { - options2.unshift({ body }); + if (data) { + options2.unshift({ body: data }); } return request(target, ...options2); }; break; case "body": - if (!body) { - body = target.body; - } - if (body) { - if (body[Symbol.metroProxy]) { - return body; - } - return bodyProxy(body, target); - } + break; + case "data": + return data; break; } if (target[prop] instanceof Function) { + if (prop === "clone") { + } return target[prop].bind(target); } return target[prop]; @@ -367,7 +264,7 @@ value = value[Symbol.metroSource]; } if (typeof value == "function") { - value(params[prop], params); + params[prop] = value(params[prop], params); } else { if (prop == "url") { params.url = new URL(value, params.url || "https://localhost/"); @@ -376,6 +273,9 @@ } } } + if (res instanceof Response && res.data) { + params.body = res.data; + } return params; } function response(...options) { @@ -393,6 +293,10 @@ } } } + let data = void 0; + if (responseParams.body) { + data = responseParams.body; + } let r = new Response(responseParams.body, responseParams); Object.freeze(r); return new Proxy(r, { @@ -409,37 +313,17 @@ return response(target, ...options2); }; break; - case "body": - if (responseParams.body) { - if (responseParams.body[Symbol.metroProxy]) { - return responseParams.body; - } - return bodyProxy(responseParams.body, target); - } else { - return bodyProxy("", target); - } + case "data": + return data; break; case "ok": return target.status >= 200 && target.status < 400; break; - case "headers": - return target.headers; - break; - default: - if (prop in responseParams && prop != "toString") { - return responseParams[prop]; - } - if (prop in target && prop != "toString") { - if (typeof target[prop] == "function") { - return function(...args) { - return target[prop].apply(target, args); - }; - } - return target[prop]; - } - break; } - return void 0; + if (typeof target[prop] == "function") { + return target[prop].bind(target); + } + return target[prop]; } }); } diff --git a/dist/browser.js.map b/dist/browser.js.map index b17155f..f92db73 100644 --- a/dist/browser.js.map +++ b/dist/browser.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/metro.mjs", "../src/browser.mjs"], - "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\t// even though a Proxy is supposed to be 'invisible'\n\t\t\t\t// fetch() doesn't work with the proxy (in Firefox), \n\t\t\t\t// you need the actual Request object here\n\t\t\t\t// and the actual body if you use e.g. FormData\n\t\t\t\tif (req.body && req.body[Symbol.metroSource]) {\n\t\t\t\t\tlet body = req.body[Symbol.metroSource]\n\t\t\t\t\treq = new Request(req[Symbol.metroSource], { body })\n\t\t\t\t} else {\n\t\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction bodyProxy(body, r)\n{\n\tlet source = r.body\n\tif (!source) {\n\t\t//Firefox does not allow access to Request.body (undefined)\n\t\t//Chrome and Nodejs do, so mimic the correct (documented)\n\t\t//result here\n\t\tif (body === null) {\n\t\t\tsource = new ReadableStream()\n\t\t} else if (body instanceof ReadableStream) {\n\t\t\tsource = body\n\t\t} else if (body instanceof Blob) {\n\t\t\tsource = body.stream()\n\t\t} else {\n\t\t\tsource = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tlet chunk\n\t\t\t\t\tswitch(typeof body) {\n\t\t\t\t\t\tcase 'object':\n\t\t\t\t\t\t\tif (typeof body.toString == 'function') {\n\t\t\t\t\t\t\t\t// also catches URLSearchParams\n\t\t\t\t\t\t\t\tchunk = body.toString()\n\t\t\t\t\t\t\t} else if (body instanceof FormData) {\n\t\t\t\t\t\t\t\tchunk = new URLSearchParams(body).toString()\n\t\t\t\t\t\t\t} else if (body instanceof ArrayBuffer\n\t\t\t\t\t\t\t\t|| ArrayBuffer.isView(body)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// catchs TypedArrays - e.g. Uint16Array\n\t\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(chunk)\n\t\t\t\t\tcontroller.close()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\treturn new Proxy(source, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch (prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn body\n\t\t\t\tbreak\n\t\t\t\tcase 'toString':\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\treturn ''+body\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\tif (prop in body) {\n\t\t\t\t\tif (typeof body[prop] == 'function') {\n\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\treturn body[prop].apply(body, args)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn body[prop]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t// and body may have its own toString\n\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop]\n\t\t\t}\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn prop in body\n\t\t\t} else {\n\t\t\t\treturn prop in target\n\t\t\t}\n\t\t},\n\t\townKeys(target) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Reflect.ownKeys(body)\n\t\t\t} else {\n\t\t\t\treturn Reflect.ownKeys(target)\n\t\t\t}\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(body,prop)\n\t\t\t} else {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(target,prop)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet body = requestParams.body\n\tif (body) {\n\t\tif (typeof body == 'object'\n\t\t\t&& !(body instanceof String)\n\t\t\t&& !(body instanceof ReadableStream)\n\t\t\t&& !(body instanceof Blob)\n\t\t\t&& !(body instanceof ArrayBuffer)\n\t\t\t&& !(body instanceof DataView)\n\t\t\t&& !(body instanceof FormData)\n\t\t\t&& !(body instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(body instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(body)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (body) { // body is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// Request.body is always a ReadableStream\n\t\t\t\t\t// which is a horrible API, if you want to\n\t\t\t\t\t// allow middleware to alter the body\n\t\t\t\t\t// so we keep the original body, wrap a Proxy\n\t\t\t\t\t// around it to keep the ReadableStream api\n\t\t\t\t\t// accessible, but allow access to the original\n\t\t\t\t\t// body value as well\n\t\t\t\t\tif (!body) {\n\t\t\t\t\t\tbody = target.body\n\t\t\t\t\t}\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tif (body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(body, target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\tif (responseParams.body) {\n\t\t\t\t\t\tif (responseParams.body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn responseParams.body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(responseParams.body, target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn bodyProxy('',target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t\tcase 'headers':\n\t\t\t\t\treturn target.headers\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (prop in responseParams && prop != 'toString') {\n\t\t\t\t\t\treturn responseParams[prop]\n\t\t\t\t\t}\n\t\t\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t\t\t// and body may have its own toString\n\t\t\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from './metro.mjs'\n\nglobalThis.metro = metro\n\nexport default metro"], - "mappings": "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", + "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n * @method fetch\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (req instanceof Request && req.data) {\n\t\t// Request.body is always transformed into ReadableStreem\n\t\t// metro.request.data is the original body passed to Request()\n\t\tparams.body = req.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet data = requestParams.body\n\tif (data) {\n\t\tif (typeof data == 'object'\n\t\t\t&& !(data instanceof String)\n\t\t\t&& !(data instanceof ReadableStream)\n\t\t\t&& !(data instanceof Blob)\n\t\t\t&& !(data instanceof ArrayBuffer)\n\t\t\t&& !(data instanceof DataView)\n\t\t\t&& !(data instanceof FormData)\n\t\t\t&& !(data instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(data instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(data)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (data) { // data is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body: data }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// FIXME: Firefox doesn't have Request.body\n\t\t\t\t\t// should we provide it here? metro.request.data\n\t\t\t\t\t// is a better alternative\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\tif (prop === 'clone') {\n\t\t\t\t\t// TODO: set req.data as the body of the clone\n\t\t\t\t}\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (res instanceof Response && res.data) {\n\t\t// Response.body is always transformed into ReadableStreem FIXME: check this\n\t\t// metro.response.data is the original body passed to Response()\n\t\tparams.body = res.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet data = undefined\n\tif (responseParams.body) {\n\t\tdata = responseParams.body\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\t// body is turned into ReadableStream\n\t\t\t\t\t// data is the original body param\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from './metro.mjs'\n\nglobalThis.metro = metro\n\nexport default metro"], + "mappings": "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", "names": ["options", "req", "next", "middleware", "options", "url"] } diff --git a/dist/browser.min.js b/dist/browser.min.js index d8bdc30..7645fca 100644 --- a/dist/browser.min.js +++ b/dist/browser.min.js @@ -1,2 +1,2 @@ -(()=>{var v=Object.defineProperty;var O=(o,n)=>{for(var r in n)v(o,r,{get:n[r],enumerable:!0})};var p={};O(p,{client:()=>A,formdata:()=>R,metroError:()=>f,request:()=>b,response:()=>P,trace:()=>L,url:()=>d});var y="https://metro.muze.nl/details/";Symbol.metroProxy||(Symbol.metroProxy=Symbol("isProxy"));Symbol.metroSource||(Symbol.metroSource=Symbol("source"));var u=class o{#e={url:typeof window<"u"?window.location:"https://localhost"};#r=["get","post","put","delete","patch","head","options","query"];static tracers={};constructor(...n){for(let r of n)if(typeof r=="string"||r instanceof String)this.#e.url=""+r;else if(r instanceof o)Object.assign(this.#e,r.#e);else if(r instanceof Function)this.#t([r]);else if(r&&typeof r=="object")for(let e in r)e=="middlewares"?this.#t(r[e]):typeof r[e]=="function"?this.#e[e]=r[e](this.#e[e],this.#e):this.#e[e]=r[e];this.#e.verbs&&(this.#r=this.#e.verbs,delete this.#e.verbs);for(let r of this.#r)this[r]=async function(...e){return this.fetch(b(this.#e,...e,{method:r.toUpperCase()}))};Object.freeze(this)}#t(n){typeof n=="function"&&(n=[n]);let r=n.findIndex(e=>typeof e!="function");if(r>=0)throw f("metro.client: middlewares must be a function or an array of functions "+y+"client/invalid-middlewares-value/",n[r]);Array.isArray(this.#e.middlewares)||(this.#e.middlewares=[]),this.#e.middlewares=this.#e.middlewares.concat(n)}fetch(n,r){if(n=b(n,r),!n.url)throw f("metro.client."+n.method.toLowerCase()+": Missing url parameter "+y+"client/missing-url-param/",n);if(r||(r={}),typeof r!="object"||Array.isArray(r)||r instanceof String)throw f("metro.client.fetch: Options is not an object");let t=[async function(a){if(a[Symbol.metroProxy])if(a.body&&a.body[Symbol.metroSource]){let h=a.body[Symbol.metroSource];a=new Request(a[Symbol.metroSource],{body:h})}else a=a[Symbol.metroSource];let l=await fetch(a);return P(l)}].concat(this.#e?.middlewares?.slice()||[]);r=Object.assign({},this.#e,r);let i;for(let s of t)i=function(a,l){return async function(h){let w,x=Object.values(o.tracers);for(let c of x)c.request&&c.request.call(c,h,l);w=await l(h,a);for(let c of x)c.response&&c.response.call(c,w,l);return w}}(i,s);return i(n)}with(...n){return new o(this,...n)}};function A(...o){return new u(...o)}function S(o,n){let r=n.body;return r||(o===null?r=new ReadableStream:o instanceof ReadableStream?r=o:o instanceof Blob?r=o.stream():r=new ReadableStream({start(e){let t;switch(typeof o){case"object":if(typeof o.toString=="function")t=o.toString();else if(o instanceof FormData)t=new URLSearchParams(o).toString();else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))t=o;else throw f("Cannot convert body to ReadableStream",o);break;case"string":case"number":case"boolean":t=o;break;default:throw f("Cannot convert body to ReadableStream",o)}e.enqueue(t),e.close()}})),new Proxy(r,{get(e,t,i){switch(t){case Symbol.metroProxy:return!0;case Symbol.metroSource:return o;case"toString":return function(){return""+o}}if(o&&typeof o=="object"&&t in o)return typeof o[t]=="function"?function(...s){return o[t].apply(o,s)}:o[t];if(t in e&&t!="toString")return typeof e[t]=="function"?function(...s){return e[t].apply(e,s)}:e[t]},has(e,t){return o&&typeof o=="object"?t in o:t in e},ownKeys(e){return Reflect.ownKeys(o&&typeof o=="object"?o:e)},getOwnPropertyDescriptor(e,t){return Object.getOwnPropertyDescriptor(o&&typeof o=="object"?o:e,t)}})}function g(o,n){let r=n||{};!r.url&&n.url&&(r.url=n.url);for(let e of["method","headers","body","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","priority","url"]){let t=o[e];if(!(typeof t>"u"||t==null))if(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function")t(r[e],r);else if(e=="url")r.url=d(r.url,t);else if(e=="headers"){r.headers=new Headers(n.headers),t instanceof Headers||(t=new Headers(o.headers));for(let[i,s]of t.entries())r.headers.set(i,s)}else r[e]=t}return r}function b(...o){let n={url:typeof window<"u"?window.location:"https://localhost/",duplex:"half"};for(let t of o)typeof t=="string"||t instanceof URL||t instanceof URLSearchParams?n.url=d(n.url,t):t&&(t instanceof FormData||t instanceof ReadableStream||t instanceof Blob||t instanceof ArrayBuffer||t instanceof DataView)?n.body=t:t&&typeof t=="object"&&Object.assign(n,g(t,n));let r=n.body;r&&typeof r=="object"&&!(r instanceof String)&&!(r instanceof ReadableStream)&&!(r instanceof Blob)&&!(r instanceof ArrayBuffer)&&!(r instanceof DataView)&&!(r instanceof FormData)&&!(r instanceof URLSearchParams)&&(typeof TypedArray>"u"||!(r instanceof TypedArray))&&(n.body=JSON.stringify(r));let e=new Request(n.url,n);return Object.freeze(e),new Proxy(e,{get(t,i,s){switch(i){case Symbol.metroSource:return t;case Symbol.metroProxy:return!0;case"with":return function(...a){return r&&a.unshift({body:r}),b(t,...a)};case"body":if(r||(r=t.body),r)return r[Symbol.metroProxy]?r:S(r,t);break}return t[i]instanceof Function?t[i].bind(t):t[i]}})}function j(o,n){let r=n||{};!r.url&&n.url&&(r.url=n.url);for(let e of["status","statusText","headers","body","url","type","redirected"]){let t=o[e];typeof t>"u"||t==null||(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function"?t(r[e],r):e=="url"?r.url=new URL(t,r.url||"https://localhost/"):r[e]=t)}return r}function P(...o){let n={};for(let e of o)typeof e=="string"?n.body=e:e instanceof Response?Object.assign(n,j(e,n)):e&&typeof e=="object"&&(e instanceof FormData||e instanceof Blob||e instanceof ArrayBuffer||e instanceof DataView||e instanceof ReadableStream||e instanceof URLSearchParams||e instanceof String||typeof TypedArray<"u"&&e instanceof TypedArray?n.body=e:Object.assign(n,j(e,n)));let r=new Response(n.body,n);return Object.freeze(r),new Proxy(r,{get(e,t,i){switch(t){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...s){return P(e,...s)};case"body":return n.body?n.body[Symbol.metroProxy]?n.body:S(n.body,e):S("",e);case"ok":return e.status>=200&&e.status<400;case"headers":return e.headers;default:if(t in n&&t!="toString")return n[t];if(t in e&&t!="toString")return typeof e[t]=="function"?function(...s){return e[t].apply(e,s)}:e[t];break}}})}function k(o,n){typeof n=="function"?n(o.searchParams,o):(n=new URLSearchParams(n),n.forEach((r,e)=>{o.searchParams.append(e,r)}))}function d(...o){let n=["hash","host","hostname","href","password","pathname","port","protocol","username","search","searchParams"],r=new URL("https://localhost/");for(let e of o)if(typeof e=="string"||e instanceof String)r=new URL(e,r);else if(e instanceof URL||typeof Location<"u"&&e instanceof Location)r=new URL(e);else if(e instanceof URLSearchParams)k(r,e);else if(e&&typeof e=="object")for(let t in e)if(t=="search")typeof e.search=="function"?e.search(r.search,r):r.search=new URLSearchParams(e.search);else if(t=="searchParams")k(r,e.searchParams);else{if(!n.includes(t))throw f("metro.url: unknown url parameter "+y+"url/unknown-param-name/",t);if(typeof e[t]=="function")e[t](r[t],r);else if(typeof e[t]=="string"||e[t]instanceof String||typeof e[t]=="number"||e[t]instanceof Number||typeof e[t]=="boolean"||e[t]instanceof Boolean)r[t]=""+e[t];else if(typeof e[t]=="object"&&e[t].toString)r[t]=e[t].toString();else throw f("metro.url: unsupported value for "+t+" "+y+"url/unsupported-param-value/",o[t])}else throw f("metro.url: unsupported option value "+y+"url/unsupported-option-value/",e);return Object.freeze(r),new Proxy(r,{get(e,t,i){switch(t){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...s){return d(e,...s)}}return e[t]instanceof Function?e[t].bind(e):e[t]}})}function R(...o){var n=new FormData;for(let r of o)if(r instanceof FormData)for(let e of r.entries())n.append(e[0],e[1]);else if(r&&typeof r=="object")for(let e of Object.entries(r))if(Array.isArray(e[1]))for(let t of e[1])n.append(e[0],t);else n.append(e[0],e[1]);else throw new f("metro.formdata: unknown option type, only FormData or Object supported",r);return Object.freeze(n),new Proxy(n,{get:(r,e,t)=>{switch(e){case Symbol.metroProxy:return!0;case Symbol.metroSource:return r;case"with":return function(...i){return R(r,...i)}}return r[e]instanceof Function?r[e].bind(r):r[e]}})}var m={error:(o,...n)=>{console.error("\u24C2\uFE0F ",o,...n)},info:(o,...n)=>{console.info("\u24C2\uFE0F ",o,...n)},group:o=>{console.group("\u24C2\uFE0F "+o)},groupEnd:o=>{console.groupEnd("\u24C2\uFE0F "+o)}};function f(o,...n){return m.error(o,...n),new Error(o,...n)}var L={add(o,n){u.tracers[o]=n},delete(o){delete u.tracers[o]},clear(){u.tracers={}},group(){let o=0;return{request:(n,r)=>{o++,m.group(o),m.info(n?.url,n,r)},response:(n,r)=>{m.info(n?.body?n.body[Symbol.metroSource]:null,n,r),m.groupEnd(o),o--}}}};globalThis.metro=p;var D=p;})(); +(()=>{var R=Object.defineProperty;var k=(n,o)=>{for(var e in o)R(n,e,{get:o[e],enumerable:!0})};var h={};k(h,{client:()=>A,formdata:()=>v,metroError:()=>f,request:()=>m,response:()=>w,trace:()=>L,url:()=>b});var d="https://metro.muze.nl/details/";Symbol.metroProxy||(Symbol.metroProxy=Symbol("isProxy"));Symbol.metroSource||(Symbol.metroSource=Symbol("source"));var l=class n{#e={url:typeof window<"u"?window.location:"https://localhost"};#t=["get","post","put","delete","patch","head","options","query"];static tracers={};constructor(...o){for(let e of o)if(typeof e=="string"||e instanceof String)this.#e.url=""+e;else if(e instanceof n)Object.assign(this.#e,e.#e);else if(e instanceof Function)this.#r([e]);else if(e&&typeof e=="object")for(let r in e)r=="middlewares"?this.#r(e[r]):typeof e[r]=="function"?this.#e[r]=e[r](this.#e[r],this.#e):this.#e[r]=e[r];this.#e.verbs&&(this.#t=this.#e.verbs,delete this.#e.verbs);for(let e of this.#t)this[e]=async function(...r){return this.fetch(m(this.#e,...r,{method:e.toUpperCase()}))};Object.freeze(this)}#r(o){typeof o=="function"&&(o=[o]);let e=o.findIndex(r=>typeof r!="function");if(e>=0)throw f("metro.client: middlewares must be a function or an array of functions "+d+"client/invalid-middlewares-value/",o[e]);Array.isArray(this.#e.middlewares)||(this.#e.middlewares=[]),this.#e.middlewares=this.#e.middlewares.concat(o)}fetch(o,e){if(o=m(o,e),!o.url)throw f("metro.client."+o.method.toLowerCase()+": Missing url parameter "+d+"client/missing-url-param/",o);if(e||(e={}),typeof e!="object"||Array.isArray(e)||e instanceof String)throw f("metro.client.fetch: Options is not an object");let t=[async function(i){i[Symbol.metroProxy]&&(i=i[Symbol.metroSource]);let u=await fetch(i);return w(u)}].concat(this.#e?.middlewares?.slice()||[]);e=Object.assign({},this.#e,e);let a;for(let s of t)a=function(i,u){return async function(S){let p,P=Object.values(n.tracers);for(let c of P)c.request&&c.request.call(c,S,u);p=await u(S,i);for(let c of P)c.response&&c.response.call(c,p,u);return p}}(a,s);return a(o)}with(...o){return new n(this,...o)}};function A(...n){return new l(...n)}function g(n,o){let e=o||{};!e.url&&o.url&&(e.url=o.url);for(let r of["method","headers","body","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","priority","url"]){let t=n[r];if(!(typeof t>"u"||t==null))if(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function")e[r]=t(e[r],e);else if(r=="url")e.url=b(e.url,t);else if(r=="headers"){e.headers=new Headers(o.headers),t instanceof Headers||(t=new Headers(n.headers));for(let[a,s]of t.entries())e.headers.set(a,s)}else e[r]=t}return n instanceof Request&&n.data&&(e.body=n.data),e}function m(...n){let o={url:typeof window<"u"?window.location:"https://localhost/",duplex:"half"};for(let t of n)typeof t=="string"||t instanceof URL||t instanceof URLSearchParams?o.url=b(o.url,t):t&&(t instanceof FormData||t instanceof ReadableStream||t instanceof Blob||t instanceof ArrayBuffer||t instanceof DataView)?o.body=t:t&&typeof t=="object"&&Object.assign(o,g(t,o));let e=o.body;e&&typeof e=="object"&&!(e instanceof String)&&!(e instanceof ReadableStream)&&!(e instanceof Blob)&&!(e instanceof ArrayBuffer)&&!(e instanceof DataView)&&!(e instanceof FormData)&&!(e instanceof URLSearchParams)&&(typeof TypedArray>"u"||!(e instanceof TypedArray))&&(o.body=JSON.stringify(e));let r=new Request(o.url,o);return Object.freeze(r),new Proxy(r,{get(t,a,s){switch(a){case Symbol.metroSource:return t;case Symbol.metroProxy:return!0;case"with":return function(...i){return e&&i.unshift({body:e}),m(t,...i)};case"body":break;case"data":return e}return t[a]instanceof Function?t[a].bind(t):t[a]}})}function x(n,o){let e=o||{};!e.url&&o.url&&(e.url=o.url);for(let r of["status","statusText","headers","body","url","type","redirected"]){let t=n[r];typeof t>"u"||t==null||(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function"?e[r]=t(e[r],e):r=="url"?e.url=new URL(t,e.url||"https://localhost/"):e[r]=t)}return n instanceof Response&&n.data&&(e.body=n.data),e}function w(...n){let o={};for(let t of n)typeof t=="string"?o.body=t:t instanceof Response?Object.assign(o,x(t,o)):t&&typeof t=="object"&&(t instanceof FormData||t instanceof Blob||t instanceof ArrayBuffer||t instanceof DataView||t instanceof ReadableStream||t instanceof URLSearchParams||t instanceof String||typeof TypedArray<"u"&&t instanceof TypedArray?o.body=t:Object.assign(o,x(t,o)));let e;o.body&&(e=o.body);let r=new Response(o.body,o);return Object.freeze(r),new Proxy(r,{get(t,a,s){switch(a){case Symbol.metroProxy:return!0;case Symbol.metroSource:return t;case"with":return function(...i){return w(t,...i)};case"data":return e;case"ok":return t.status>=200&&t.status<400}return typeof t[a]=="function"?t[a].bind(t):t[a]}})}function j(n,o){typeof o=="function"?o(n.searchParams,n):(o=new URLSearchParams(o),o.forEach((e,r)=>{n.searchParams.append(r,e)}))}function b(...n){let o=["hash","host","hostname","href","password","pathname","port","protocol","username","search","searchParams"],e=new URL("https://localhost/");for(let r of n)if(typeof r=="string"||r instanceof String)e=new URL(r,e);else if(r instanceof URL||typeof Location<"u"&&r instanceof Location)e=new URL(r);else if(r instanceof URLSearchParams)j(e,r);else if(r&&typeof r=="object")for(let t in r)if(t=="search")typeof r.search=="function"?r.search(e.search,e):e.search=new URLSearchParams(r.search);else if(t=="searchParams")j(e,r.searchParams);else{if(!o.includes(t))throw f("metro.url: unknown url parameter "+d+"url/unknown-param-name/",t);if(typeof r[t]=="function")r[t](e[t],e);else if(typeof r[t]=="string"||r[t]instanceof String||typeof r[t]=="number"||r[t]instanceof Number||typeof r[t]=="boolean"||r[t]instanceof Boolean)e[t]=""+r[t];else if(typeof r[t]=="object"&&r[t].toString)e[t]=r[t].toString();else throw f("metro.url: unsupported value for "+t+" "+d+"url/unsupported-param-value/",n[t])}else throw f("metro.url: unsupported option value "+d+"url/unsupported-option-value/",r);return Object.freeze(e),new Proxy(e,{get(r,t,a){switch(t){case Symbol.metroProxy:return!0;case Symbol.metroSource:return r;case"with":return function(...s){return b(r,...s)}}return r[t]instanceof Function?r[t].bind(r):r[t]}})}function v(...n){var o=new FormData;for(let e of n)if(e instanceof FormData)for(let r of e.entries())o.append(r[0],r[1]);else if(e&&typeof e=="object")for(let r of Object.entries(e))if(Array.isArray(r[1]))for(let t of r[1])o.append(r[0],t);else o.append(r[0],r[1]);else throw new f("metro.formdata: unknown option type, only FormData or Object supported",e);return Object.freeze(o),new Proxy(o,{get:(e,r,t)=>{switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...a){return v(e,...a)}}return e[r]instanceof Function?e[r].bind(e):e[r]}})}var y={error:(n,...o)=>{console.error("\u24C2\uFE0F ",n,...o)},info:(n,...o)=>{console.info("\u24C2\uFE0F ",n,...o)},group:n=>{console.group("\u24C2\uFE0F "+n)},groupEnd:n=>{console.groupEnd("\u24C2\uFE0F "+n)}};function f(n,...o){return y.error(n,...o),new Error(n,...o)}var L={add(n,o){l.tracers[n]=o},delete(n){delete l.tracers[n]},clear(){l.tracers={}},group(){let n=0;return{request:(o,e)=>{n++,y.group(n),y.info(o?.url,o,e)},response:(o,e)=>{y.info(o?.body?o.body[Symbol.metroSource]:null,o,e),y.groupEnd(n),n--}}}};globalThis.metro=h;var U=h;})(); //# sourceMappingURL=browser.min.js.map diff --git a/dist/browser.min.js.map b/dist/browser.min.js.map index 86a2f4e..bb6016f 100644 --- a/dist/browser.min.js.map +++ b/dist/browser.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/metro.mjs", "../src/browser.mjs"], - "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\t// even though a Proxy is supposed to be 'invisible'\n\t\t\t\t// fetch() doesn't work with the proxy (in Firefox), \n\t\t\t\t// you need the actual Request object here\n\t\t\t\t// and the actual body if you use e.g. FormData\n\t\t\t\tif (req.body && req.body[Symbol.metroSource]) {\n\t\t\t\t\tlet body = req.body[Symbol.metroSource]\n\t\t\t\t\treq = new Request(req[Symbol.metroSource], { body })\n\t\t\t\t} else {\n\t\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction bodyProxy(body, r)\n{\n\tlet source = r.body\n\tif (!source) {\n\t\t//Firefox does not allow access to Request.body (undefined)\n\t\t//Chrome and Nodejs do, so mimic the correct (documented)\n\t\t//result here\n\t\tif (body === null) {\n\t\t\tsource = new ReadableStream()\n\t\t} else if (body instanceof ReadableStream) {\n\t\t\tsource = body\n\t\t} else if (body instanceof Blob) {\n\t\t\tsource = body.stream()\n\t\t} else {\n\t\t\tsource = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tlet chunk\n\t\t\t\t\tswitch(typeof body) {\n\t\t\t\t\t\tcase 'object':\n\t\t\t\t\t\t\tif (typeof body.toString == 'function') {\n\t\t\t\t\t\t\t\t// also catches URLSearchParams\n\t\t\t\t\t\t\t\tchunk = body.toString()\n\t\t\t\t\t\t\t} else if (body instanceof FormData) {\n\t\t\t\t\t\t\t\tchunk = new URLSearchParams(body).toString()\n\t\t\t\t\t\t\t} else if (body instanceof ArrayBuffer\n\t\t\t\t\t\t\t\t|| ArrayBuffer.isView(body)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// catchs TypedArrays - e.g. Uint16Array\n\t\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(chunk)\n\t\t\t\t\tcontroller.close()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\treturn new Proxy(source, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch (prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn body\n\t\t\t\tbreak\n\t\t\t\tcase 'toString':\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\treturn ''+body\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\tif (prop in body) {\n\t\t\t\t\tif (typeof body[prop] == 'function') {\n\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\treturn body[prop].apply(body, args)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn body[prop]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t// and body may have its own toString\n\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop]\n\t\t\t}\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn prop in body\n\t\t\t} else {\n\t\t\t\treturn prop in target\n\t\t\t}\n\t\t},\n\t\townKeys(target) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Reflect.ownKeys(body)\n\t\t\t} else {\n\t\t\t\treturn Reflect.ownKeys(target)\n\t\t\t}\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(body,prop)\n\t\t\t} else {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(target,prop)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet body = requestParams.body\n\tif (body) {\n\t\tif (typeof body == 'object'\n\t\t\t&& !(body instanceof String)\n\t\t\t&& !(body instanceof ReadableStream)\n\t\t\t&& !(body instanceof Blob)\n\t\t\t&& !(body instanceof ArrayBuffer)\n\t\t\t&& !(body instanceof DataView)\n\t\t\t&& !(body instanceof FormData)\n\t\t\t&& !(body instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(body instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(body)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (body) { // body is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// Request.body is always a ReadableStream\n\t\t\t\t\t// which is a horrible API, if you want to\n\t\t\t\t\t// allow middleware to alter the body\n\t\t\t\t\t// so we keep the original body, wrap a Proxy\n\t\t\t\t\t// around it to keep the ReadableStream api\n\t\t\t\t\t// accessible, but allow access to the original\n\t\t\t\t\t// body value as well\n\t\t\t\t\tif (!body) {\n\t\t\t\t\t\tbody = target.body\n\t\t\t\t\t}\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tif (body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(body, target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\tif (responseParams.body) {\n\t\t\t\t\t\tif (responseParams.body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn responseParams.body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(responseParams.body, target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn bodyProxy('',target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t\tcase 'headers':\n\t\t\t\t\treturn target.headers\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (prop in responseParams && prop != 'toString') {\n\t\t\t\t\t\treturn responseParams[prop]\n\t\t\t\t\t}\n\t\t\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t\t\t// and body may have its own toString\n\t\t\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from './metro.mjs'\n\nglobalThis.metro = metro\n\nexport default metro"], - "mappings": "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", - "names": ["metro_exports", "__export", "client", "formdata", "metroError", "request", "response", "trace", "url", "metroURL", "Client", "_Client", "#options", "#verbs", "options", "option", "#addMiddlewares", "param", "verb", "middlewares", "index", "m", "req", "body", "res", "next", "middleware", "tracers", "tracer", "bodyProxy", "body", "r", "source", "controller", "chunk", "metroError", "target", "prop", "receiver", "args", "getRequestParams", "req", "current", "params", "value", "url", "key", "val", "request", "options", "requestParams", "option", "getResponseParams", "res", "response", "responseParams", "appendSearchParams", "validParams", "u", "param", "metroURL", "formdata", "entry", "metroConsole", "message", "details", "name", "trace", "tracer", "Client", "group", "middleware", "metro_exports", "browser_default"] + "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n * @method fetch\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (req instanceof Request && req.data) {\n\t\t// Request.body is always transformed into ReadableStreem\n\t\t// metro.request.data is the original body passed to Request()\n\t\tparams.body = req.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet data = requestParams.body\n\tif (data) {\n\t\tif (typeof data == 'object'\n\t\t\t&& !(data instanceof String)\n\t\t\t&& !(data instanceof ReadableStream)\n\t\t\t&& !(data instanceof Blob)\n\t\t\t&& !(data instanceof ArrayBuffer)\n\t\t\t&& !(data instanceof DataView)\n\t\t\t&& !(data instanceof FormData)\n\t\t\t&& !(data instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(data instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(data)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (data) { // data is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body: data }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// FIXME: Firefox doesn't have Request.body\n\t\t\t\t\t// should we provide it here? metro.request.data\n\t\t\t\t\t// is a better alternative\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\tif (prop === 'clone') {\n\t\t\t\t\t// TODO: set req.data as the body of the clone\n\t\t\t\t}\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (res instanceof Response && res.data) {\n\t\t// Response.body is always transformed into ReadableStreem FIXME: check this\n\t\t// metro.response.data is the original body passed to Response()\n\t\tparams.body = res.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet data = undefined\n\tif (responseParams.body) {\n\t\tdata = responseParams.body\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\t// body is turned into ReadableStream\n\t\t\t\t\t// data is the original body param\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from './metro.mjs'\n\nglobalThis.metro = metro\n\nexport default metro"], + "mappings": "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", + "names": ["metro_exports", "__export", "client", "formdata", "metroError", "request", "response", "trace", "url", "metroURL", "Client", "_Client", "#options", "#verbs", "options", "option", "#addMiddlewares", "param", "verb", "middlewares", "index", "m", "req", "res", "next", "middleware", "tracers", "tracer", "getRequestParams", "req", "current", "params", "prop", "value", "url", "key", "val", "request", "options", "requestParams", "option", "data", "target", "receiver", "getResponseParams", "res", "response", "responseParams", "appendSearchParams", "validParams", "u", "param", "metroError", "metroURL", "formdata", "entry", "metroConsole", "message", "details", "name", "trace", "tracer", "Client", "group", "middleware", "metro_exports", "browser_default"] } diff --git a/dist/everything.js b/dist/everything.js index b4e5a6f..e088658 100644 --- a/dist/everything.js +++ b/dist/everything.js @@ -107,12 +107,7 @@ } const metrofetch = async function browserFetch(req2) { if (req2[Symbol.metroProxy]) { - if (req2.body && req2.body[Symbol.metroSource]) { - let body = req2.body[Symbol.metroSource]; - req2 = new Request(req2[Symbol.metroSource], { body }); - } else { - req2 = req2[Symbol.metroSource]; - } + req2 = req2[Symbol.metroSource]; } const res = await fetch(req2); return response(res); @@ -149,103 +144,6 @@ function client(...options) { return new Client(...options); } - function bodyProxy(body, r) { - let source = r.body; - if (!source) { - if (body === null) { - source = new ReadableStream(); - } else if (body instanceof ReadableStream) { - source = body; - } else if (body instanceof Blob) { - source = body.stream(); - } else { - source = new ReadableStream({ - start(controller) { - let chunk; - switch (typeof body) { - case "object": - if (typeof body.toString == "function") { - chunk = body.toString(); - } else if (body instanceof FormData) { - chunk = new URLSearchParams(body).toString(); - } else if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) { - chunk = body; - } else { - throw metroError("Cannot convert body to ReadableStream", body); - } - break; - case "string": - case "number": - case "boolean": - chunk = body; - break; - default: - throw metroError("Cannot convert body to ReadableStream", body); - break; - } - controller.enqueue(chunk); - controller.close(); - } - }); - } - } - return new Proxy(source, { - get(target, prop, receiver) { - switch (prop) { - case Symbol.metroProxy: - return true; - break; - case Symbol.metroSource: - return body; - break; - case "toString": - return function() { - return "" + body; - }; - break; - } - if (body && typeof body == "object") { - if (prop in body) { - if (typeof body[prop] == "function") { - return function(...args) { - return body[prop].apply(body, args); - }; - } - return body[prop]; - } - } - if (prop in target && prop != "toString") { - if (typeof target[prop] == "function") { - return function(...args) { - return target[prop].apply(target, args); - }; - } - return target[prop]; - } - }, - has(target, prop) { - if (body && typeof body == "object") { - return prop in body; - } else { - return prop in target; - } - }, - ownKeys(target) { - if (body && typeof body == "object") { - return Reflect.ownKeys(body); - } else { - return Reflect.ownKeys(target); - } - }, - getOwnPropertyDescriptor(target, prop) { - if (body && typeof body == "object") { - return Object.getOwnPropertyDescriptor(body, prop); - } else { - return Object.getOwnPropertyDescriptor(target, prop); - } - } - }); - } function getRequestParams(req, current) { let params = current || {}; if (!params.url && current.url) { @@ -275,7 +173,7 @@ value = value[Symbol.metroSource]; } if (typeof value == "function") { - value(params[prop], params); + params[prop] = value(params[prop], params); } else { if (prop == "url") { params.url = url(params.url, value); @@ -292,6 +190,9 @@ } } } + if (req instanceof Request && req.data) { + params.body = req.data; + } return params; } function request(...options) { @@ -309,10 +210,10 @@ Object.assign(requestParams, getRequestParams(option, requestParams)); } } - let body = requestParams.body; - if (body) { - if (typeof body == "object" && !(body instanceof String) && !(body instanceof ReadableStream) && !(body instanceof Blob) && !(body instanceof ArrayBuffer) && !(body instanceof DataView) && !(body instanceof FormData) && !(body instanceof URLSearchParams) && (typeof TypedArray == "undefined" || !(body instanceof TypedArray))) { - requestParams.body = JSON.stringify(body); + let data = requestParams.body; + if (data) { + if (typeof data == "object" && !(data instanceof String) && !(data instanceof ReadableStream) && !(data instanceof Blob) && !(data instanceof ArrayBuffer) && !(data instanceof DataView) && !(data instanceof FormData) && !(data instanceof URLSearchParams) && (typeof TypedArray == "undefined" || !(data instanceof TypedArray))) { + requestParams.body = JSON.stringify(data); } } let r = new Request(requestParams.url, requestParams); @@ -328,25 +229,21 @@ break; case "with": return function(...options2) { - if (body) { - options2.unshift({ body }); + if (data) { + options2.unshift({ body: data }); } return request(target, ...options2); }; break; case "body": - if (!body) { - body = target.body; - } - if (body) { - if (body[Symbol.metroProxy]) { - return body; - } - return bodyProxy(body, target); - } + break; + case "data": + return data; break; } if (target[prop] instanceof Function) { + if (prop === "clone") { + } return target[prop].bind(target); } return target[prop]; @@ -367,7 +264,7 @@ value = value[Symbol.metroSource]; } if (typeof value == "function") { - value(params[prop], params); + params[prop] = value(params[prop], params); } else { if (prop == "url") { params.url = new URL(value, params.url || "https://localhost/"); @@ -376,6 +273,9 @@ } } } + if (res instanceof Response && res.data) { + params.body = res.data; + } return params; } function response(...options) { @@ -393,6 +293,10 @@ } } } + let data = void 0; + if (responseParams.body) { + data = responseParams.body; + } let r = new Response(responseParams.body, responseParams); Object.freeze(r); return new Proxy(r, { @@ -409,37 +313,17 @@ return response(target, ...options2); }; break; - case "body": - if (responseParams.body) { - if (responseParams.body[Symbol.metroProxy]) { - return responseParams.body; - } - return bodyProxy(responseParams.body, target); - } else { - return bodyProxy("", target); - } + case "data": + return data; break; case "ok": return target.status >= 200 && target.status < 400; break; - case "headers": - return target.headers; - break; - default: - if (prop in responseParams && prop != "toString") { - return responseParams[prop]; - } - if (prop in target && prop != "toString") { - if (typeof target[prop] == "function") { - return function(...args) { - return target[prop].apply(target, args); - }; - } - return target[prop]; - } - break; } - return void 0; + if (typeof target[prop] == "function") { + return target[prop].bind(target); + } + return target[prop]; } }); } @@ -648,9 +532,9 @@ "Accept": "application/json" } }); - if (req.body && typeof req.body[Symbol.metroSource] == "object") { + if (req.data && typeof req.data == "object" && !(req.data instanceof ReadableStream)) { req = req.with({ - body: JSON.stringify(req.body[Symbol.metroSource], options.replacer, options.space) + body: JSON.stringify(req.data, options.replacer, options.space) }); } } else { diff --git a/dist/everything.js.map b/dist/everything.js.map index 353ba29..55e5b90 100644 --- a/dist/everything.js.map +++ b/dist/everything.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/metro.mjs", "../src/mw/json.mjs", "../src/mw/thrower.mjs", "../src/everything.mjs"], - "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\t// even though a Proxy is supposed to be 'invisible'\n\t\t\t\t// fetch() doesn't work with the proxy (in Firefox), \n\t\t\t\t// you need the actual Request object here\n\t\t\t\t// and the actual body if you use e.g. FormData\n\t\t\t\tif (req.body && req.body[Symbol.metroSource]) {\n\t\t\t\t\tlet body = req.body[Symbol.metroSource]\n\t\t\t\t\treq = new Request(req[Symbol.metroSource], { body })\n\t\t\t\t} else {\n\t\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction bodyProxy(body, r)\n{\n\tlet source = r.body\n\tif (!source) {\n\t\t//Firefox does not allow access to Request.body (undefined)\n\t\t//Chrome and Nodejs do, so mimic the correct (documented)\n\t\t//result here\n\t\tif (body === null) {\n\t\t\tsource = new ReadableStream()\n\t\t} else if (body instanceof ReadableStream) {\n\t\t\tsource = body\n\t\t} else if (body instanceof Blob) {\n\t\t\tsource = body.stream()\n\t\t} else {\n\t\t\tsource = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tlet chunk\n\t\t\t\t\tswitch(typeof body) {\n\t\t\t\t\t\tcase 'object':\n\t\t\t\t\t\t\tif (typeof body.toString == 'function') {\n\t\t\t\t\t\t\t\t// also catches URLSearchParams\n\t\t\t\t\t\t\t\tchunk = body.toString()\n\t\t\t\t\t\t\t} else if (body instanceof FormData) {\n\t\t\t\t\t\t\t\tchunk = new URLSearchParams(body).toString()\n\t\t\t\t\t\t\t} else if (body instanceof ArrayBuffer\n\t\t\t\t\t\t\t\t|| ArrayBuffer.isView(body)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// catchs TypedArrays - e.g. Uint16Array\n\t\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(chunk)\n\t\t\t\t\tcontroller.close()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\treturn new Proxy(source, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch (prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn body\n\t\t\t\tbreak\n\t\t\t\tcase 'toString':\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\treturn ''+body\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\tif (prop in body) {\n\t\t\t\t\tif (typeof body[prop] == 'function') {\n\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\treturn body[prop].apply(body, args)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn body[prop]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t// and body may have its own toString\n\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop]\n\t\t\t}\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn prop in body\n\t\t\t} else {\n\t\t\t\treturn prop in target\n\t\t\t}\n\t\t},\n\t\townKeys(target) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Reflect.ownKeys(body)\n\t\t\t} else {\n\t\t\t\treturn Reflect.ownKeys(target)\n\t\t\t}\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(body,prop)\n\t\t\t} else {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(target,prop)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet body = requestParams.body\n\tif (body) {\n\t\tif (typeof body == 'object'\n\t\t\t&& !(body instanceof String)\n\t\t\t&& !(body instanceof ReadableStream)\n\t\t\t&& !(body instanceof Blob)\n\t\t\t&& !(body instanceof ArrayBuffer)\n\t\t\t&& !(body instanceof DataView)\n\t\t\t&& !(body instanceof FormData)\n\t\t\t&& !(body instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(body instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(body)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (body) { // body is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// Request.body is always a ReadableStream\n\t\t\t\t\t// which is a horrible API, if you want to\n\t\t\t\t\t// allow middleware to alter the body\n\t\t\t\t\t// so we keep the original body, wrap a Proxy\n\t\t\t\t\t// around it to keep the ReadableStream api\n\t\t\t\t\t// accessible, but allow access to the original\n\t\t\t\t\t// body value as well\n\t\t\t\t\tif (!body) {\n\t\t\t\t\t\tbody = target.body\n\t\t\t\t\t}\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tif (body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(body, target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\tif (responseParams.body) {\n\t\t\t\t\t\tif (responseParams.body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn responseParams.body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(responseParams.body, target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn bodyProxy('',target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t\tcase 'headers':\n\t\t\t\t\treturn target.headers\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (prop in responseParams && prop != 'toString') {\n\t\t\t\t\t\treturn responseParams[prop]\n\t\t\t\t\t}\n\t\t\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t\t\t// and body may have its own toString\n\t\t\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from '../metro.mjs'\n\nexport default function jsonmw(options) {\n\toptions = Object.assign({\n\t\treviver: null,\n\t\treplacer: null,\n\t\tspace: ''\n\t}, options)\n\n\treturn async (req, next) => {\n\t\tif (['POST','PUT','PATCH','QUERY'].includes(req.method)) {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type':'application/json',\n\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t\tif (req.body && typeof req.body[Symbol.metroSource] == 'object') {\n\t\t\t\treq = req.with({\n\t\t\t\t\tbody: JSON.stringify(req.body[Symbol.metroSource], options.replacer, options.space)\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tlet res = await next(req)\n\t\tlet body = await res.text()\n\t\tlet json = JSON.parse(body, options.reviver)\n\t\treturn res.with({\n\t\t\tbody: json\n\t\t})\n\t}\n}", "import * as metro from '../metro.mjs'\n\nexport default function thrower(options) {\n\n\treturn async (req, next) => {\n\t\tlet res = await next(req)\n\t\tif (!res.ok) {\n\t\t\tif (options && typeof options[res.status] == 'function') {\n\t\t\t\tres = options[res.status].apply(res, req)\n\t\t\t} else {\n\t\t\t\tthrow new Error(res.status+': '+res.statusText, {\n\t\t\t\t\tcause: res\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n}", "import * as m from './metro.mjs'\nimport jsonmw from './mw/json.mjs'\nimport thrower from './mw/thrower.mjs'\n\nconst metro = Object.assign({}, m, {\n\tmw: {\n\t\tjsonmw,\n\t\tthrower\n\t}\n})\n\nglobalThis.metro = metro\n\nexport default metro"], - "mappings": "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", + "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n * @method fetch\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (req instanceof Request && req.data) {\n\t\t// Request.body is always transformed into ReadableStreem\n\t\t// metro.request.data is the original body passed to Request()\n\t\tparams.body = req.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet data = requestParams.body\n\tif (data) {\n\t\tif (typeof data == 'object'\n\t\t\t&& !(data instanceof String)\n\t\t\t&& !(data instanceof ReadableStream)\n\t\t\t&& !(data instanceof Blob)\n\t\t\t&& !(data instanceof ArrayBuffer)\n\t\t\t&& !(data instanceof DataView)\n\t\t\t&& !(data instanceof FormData)\n\t\t\t&& !(data instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(data instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(data)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (data) { // data is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body: data }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// FIXME: Firefox doesn't have Request.body\n\t\t\t\t\t// should we provide it here? metro.request.data\n\t\t\t\t\t// is a better alternative\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\tif (prop === 'clone') {\n\t\t\t\t\t// TODO: set req.data as the body of the clone\n\t\t\t\t}\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (res instanceof Response && res.data) {\n\t\t// Response.body is always transformed into ReadableStreem FIXME: check this\n\t\t// metro.response.data is the original body passed to Response()\n\t\tparams.body = res.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet data = undefined\n\tif (responseParams.body) {\n\t\tdata = responseParams.body\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\t// body is turned into ReadableStream\n\t\t\t\t\t// data is the original body param\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from '../metro.mjs'\n\nexport default function jsonmw(options) {\n\toptions = Object.assign({\n\t\treviver: null,\n\t\treplacer: null,\n\t\tspace: ''\n\t}, options)\n\n\treturn async (req, next) => {\n\t\tif (['POST','PUT','PATCH','QUERY'].includes(req.method)) {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type':'application/json',\n\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t\tif (req.data && typeof req.data=='object' && !(req.data instanceof ReadableStream)) {\n\t\t\t\treq = req.with({\n\t\t\t\t\tbody: JSON.stringify(req.data, options.replacer, options.space)\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tlet res = await next(req)\n\t\tlet body = await res.text()\n\t\tlet json = JSON.parse(body, options.reviver)\n\t\treturn res.with({\n\t\t\tbody: json\n\t\t})\n\t}\n}", "import * as metro from '../metro.mjs'\n\nexport default function thrower(options) {\n\n\treturn async (req, next) => {\n\t\tlet res = await next(req)\n\t\tif (!res.ok) {\n\t\t\tif (options && typeof options[res.status] == 'function') {\n\t\t\t\tres = options[res.status].apply(res, req)\n\t\t\t} else {\n\t\t\t\tthrow new Error(res.status+': '+res.statusText, {\n\t\t\t\t\tcause: res\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n}", "import * as m from './metro.mjs'\nimport jsonmw from './mw/json.mjs'\nimport thrower from './mw/thrower.mjs'\n\nconst metro = Object.assign({}, m, {\n\tmw: {\n\t\tjsonmw,\n\t\tthrower\n\t}\n})\n\nglobalThis.metro = metro\n\nexport default metro"], + "mappings": "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", "names": ["options", "req", "next", "middleware", "options", "url"] } diff --git a/dist/everything.min.js b/dist/everything.min.js index 07b8532..e622f3a 100644 --- a/dist/everything.min.js +++ b/dist/everything.min.js @@ -1,2 +1,2 @@ -(()=>{var g=Object.defineProperty;var L=(o,n)=>{for(var t in n)g(o,t,{get:n[t],enumerable:!0})};var P={};L(P,{client:()=>U,formdata:()=>O,metroError:()=>f,request:()=>b,response:()=>S,trace:()=>F,url:()=>d});var y="https://metro.muze.nl/details/";Symbol.metroProxy||(Symbol.metroProxy=Symbol("isProxy"));Symbol.metroSource||(Symbol.metroSource=Symbol("source"));var u=class o{#e={url:typeof window<"u"?window.location:"https://localhost"};#t=["get","post","put","delete","patch","head","options","query"];static tracers={};constructor(...n){for(let t of n)if(typeof t=="string"||t instanceof String)this.#e.url=""+t;else if(t instanceof o)Object.assign(this.#e,t.#e);else if(t instanceof Function)this.#r([t]);else if(t&&typeof t=="object")for(let e in t)e=="middlewares"?this.#r(t[e]):typeof t[e]=="function"?this.#e[e]=t[e](this.#e[e],this.#e):this.#e[e]=t[e];this.#e.verbs&&(this.#t=this.#e.verbs,delete this.#e.verbs);for(let t of this.#t)this[t]=async function(...e){return this.fetch(b(this.#e,...e,{method:t.toUpperCase()}))};Object.freeze(this)}#r(n){typeof n=="function"&&(n=[n]);let t=n.findIndex(e=>typeof e!="function");if(t>=0)throw f("metro.client: middlewares must be a function or an array of functions "+y+"client/invalid-middlewares-value/",n[t]);Array.isArray(this.#e.middlewares)||(this.#e.middlewares=[]),this.#e.middlewares=this.#e.middlewares.concat(n)}fetch(n,t){if(n=b(n,t),!n.url)throw f("metro.client."+n.method.toLowerCase()+": Missing url parameter "+y+"client/missing-url-param/",n);if(t||(t={}),typeof t!="object"||Array.isArray(t)||t instanceof String)throw f("metro.client.fetch: Options is not an object");let r=[async function(a){if(a[Symbol.metroProxy])if(a.body&&a.body[Symbol.metroSource]){let h=a.body[Symbol.metroSource];a=new Request(a[Symbol.metroSource],{body:h})}else a=a[Symbol.metroSource];let l=await fetch(a);return S(l)}].concat(this.#e?.middlewares?.slice()||[]);t=Object.assign({},this.#e,t);let i;for(let s of r)i=function(a,l){return async function(h){let p,k=Object.values(o.tracers);for(let c of k)c.request&&c.request.call(c,h,l);p=await l(h,a);for(let c of k)c.response&&c.response.call(c,p,l);return p}}(i,s);return i(n)}with(...n){return new o(this,...n)}};function U(...o){return new u(...o)}function w(o,n){let t=n.body;return t||(o===null?t=new ReadableStream:o instanceof ReadableStream?t=o:o instanceof Blob?t=o.stream():t=new ReadableStream({start(e){let r;switch(typeof o){case"object":if(typeof o.toString=="function")r=o.toString();else if(o instanceof FormData)r=new URLSearchParams(o).toString();else if(o instanceof ArrayBuffer||ArrayBuffer.isView(o))r=o;else throw f("Cannot convert body to ReadableStream",o);break;case"string":case"number":case"boolean":r=o;break;default:throw f("Cannot convert body to ReadableStream",o)}e.enqueue(r),e.close()}})),new Proxy(t,{get(e,r,i){switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return o;case"toString":return function(){return""+o}}if(o&&typeof o=="object"&&r in o)return typeof o[r]=="function"?function(...s){return o[r].apply(o,s)}:o[r];if(r in e&&r!="toString")return typeof e[r]=="function"?function(...s){return e[r].apply(e,s)}:e[r]},has(e,r){return o&&typeof o=="object"?r in o:r in e},ownKeys(e){return Reflect.ownKeys(o&&typeof o=="object"?o:e)},getOwnPropertyDescriptor(e,r){return Object.getOwnPropertyDescriptor(o&&typeof o=="object"?o:e,r)}})}function D(o,n){let t=n||{};!t.url&&n.url&&(t.url=n.url);for(let e of["method","headers","body","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","priority","url"]){let r=o[e];if(!(typeof r>"u"||r==null))if(r?.[Symbol.metroProxy]&&(r=r[Symbol.metroSource]),typeof r=="function")r(t[e],t);else if(e=="url")t.url=d(t.url,r);else if(e=="headers"){t.headers=new Headers(n.headers),r instanceof Headers||(r=new Headers(o.headers));for(let[i,s]of r.entries())t.headers.set(i,s)}else t[e]=r}return t}function b(...o){let n={url:typeof window<"u"?window.location:"https://localhost/",duplex:"half"};for(let r of o)typeof r=="string"||r instanceof URL||r instanceof URLSearchParams?n.url=d(n.url,r):r&&(r instanceof FormData||r instanceof ReadableStream||r instanceof Blob||r instanceof ArrayBuffer||r instanceof DataView)?n.body=r:r&&typeof r=="object"&&Object.assign(n,D(r,n));let t=n.body;t&&typeof t=="object"&&!(t instanceof String)&&!(t instanceof ReadableStream)&&!(t instanceof Blob)&&!(t instanceof ArrayBuffer)&&!(t instanceof DataView)&&!(t instanceof FormData)&&!(t instanceof URLSearchParams)&&(typeof TypedArray>"u"||!(t instanceof TypedArray))&&(n.body=JSON.stringify(t));let e=new Request(n.url,n);return Object.freeze(e),new Proxy(e,{get(r,i,s){switch(i){case Symbol.metroSource:return r;case Symbol.metroProxy:return!0;case"with":return function(...a){return t&&a.unshift({body:t}),b(r,...a)};case"body":if(t||(t=r.body),t)return t[Symbol.metroProxy]?t:w(t,r);break}return r[i]instanceof Function?r[i].bind(r):r[i]}})}function R(o,n){let t=n||{};!t.url&&n.url&&(t.url=n.url);for(let e of["status","statusText","headers","body","url","type","redirected"]){let r=o[e];typeof r>"u"||r==null||(r?.[Symbol.metroProxy]&&(r=r[Symbol.metroSource]),typeof r=="function"?r(t[e],t):e=="url"?t.url=new URL(r,t.url||"https://localhost/"):t[e]=r)}return t}function S(...o){let n={};for(let e of o)typeof e=="string"?n.body=e:e instanceof Response?Object.assign(n,R(e,n)):e&&typeof e=="object"&&(e instanceof FormData||e instanceof Blob||e instanceof ArrayBuffer||e instanceof DataView||e instanceof ReadableStream||e instanceof URLSearchParams||e instanceof String||typeof TypedArray<"u"&&e instanceof TypedArray?n.body=e:Object.assign(n,R(e,n)));let t=new Response(n.body,n);return Object.freeze(t),new Proxy(t,{get(e,r,i){switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...s){return S(e,...s)};case"body":return n.body?n.body[Symbol.metroProxy]?n.body:w(n.body,e):w("",e);case"ok":return e.status>=200&&e.status<400;case"headers":return e.headers;default:if(r in n&&r!="toString")return n[r];if(r in e&&r!="toString")return typeof e[r]=="function"?function(...s){return e[r].apply(e,s)}:e[r];break}}})}function v(o,n){typeof n=="function"?n(o.searchParams,o):(n=new URLSearchParams(n),n.forEach((t,e)=>{o.searchParams.append(e,t)}))}function d(...o){let n=["hash","host","hostname","href","password","pathname","port","protocol","username","search","searchParams"],t=new URL("https://localhost/");for(let e of o)if(typeof e=="string"||e instanceof String)t=new URL(e,t);else if(e instanceof URL||typeof Location<"u"&&e instanceof Location)t=new URL(e);else if(e instanceof URLSearchParams)v(t,e);else if(e&&typeof e=="object")for(let r in e)if(r=="search")typeof e.search=="function"?e.search(t.search,t):t.search=new URLSearchParams(e.search);else if(r=="searchParams")v(t,e.searchParams);else{if(!n.includes(r))throw f("metro.url: unknown url parameter "+y+"url/unknown-param-name/",r);if(typeof e[r]=="function")e[r](t[r],t);else if(typeof e[r]=="string"||e[r]instanceof String||typeof e[r]=="number"||e[r]instanceof Number||typeof e[r]=="boolean"||e[r]instanceof Boolean)t[r]=""+e[r];else if(typeof e[r]=="object"&&e[r].toString)t[r]=e[r].toString();else throw f("metro.url: unsupported value for "+r+" "+y+"url/unsupported-param-value/",o[r])}else throw f("metro.url: unsupported option value "+y+"url/unsupported-option-value/",e);return Object.freeze(t),new Proxy(t,{get(e,r,i){switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...s){return d(e,...s)}}return e[r]instanceof Function?e[r].bind(e):e[r]}})}function O(...o){var n=new FormData;for(let t of o)if(t instanceof FormData)for(let e of t.entries())n.append(e[0],e[1]);else if(t&&typeof t=="object")for(let e of Object.entries(t))if(Array.isArray(e[1]))for(let r of e[1])n.append(e[0],r);else n.append(e[0],e[1]);else throw new f("metro.formdata: unknown option type, only FormData or Object supported",t);return Object.freeze(n),new Proxy(n,{get:(t,e,r)=>{switch(e){case Symbol.metroProxy:return!0;case Symbol.metroSource:return t;case"with":return function(...i){return O(t,...i)}}return t[e]instanceof Function?t[e].bind(t):t[e]}})}var m={error:(o,...n)=>{console.error("\u24C2\uFE0F ",o,...n)},info:(o,...n)=>{console.info("\u24C2\uFE0F ",o,...n)},group:o=>{console.group("\u24C2\uFE0F "+o)},groupEnd:o=>{console.groupEnd("\u24C2\uFE0F "+o)}};function f(o,...n){return m.error(o,...n),new Error(o,...n)}var F={add(o,n){u.tracers[o]=n},delete(o){delete u.tracers[o]},clear(){u.tracers={}},group(){let o=0;return{request:(n,t)=>{o++,m.group(o),m.info(n?.url,n,t)},response:(n,t)=>{m.info(n?.body?n.body[Symbol.metroSource]:null,n,t),m.groupEnd(o),o--}}}};function j(o){return o=Object.assign({reviver:null,replacer:null,space:""},o),async(n,t)=>{["POST","PUT","PATCH","QUERY"].includes(n.method)?(n=n.with({headers:{"Content-Type":"application/json",Accept:"application/json"}}),n.body&&typeof n.body[Symbol.metroSource]=="object"&&(n=n.with({body:JSON.stringify(n.body[Symbol.metroSource],o.replacer,o.space)}))):n=n.with({headers:{Accept:"application/json"}});let e=await t(n),r=await e.text(),i=JSON.parse(r,o.reviver);return e.with({body:i})}}function x(o){return async(n,t)=>{let e=await t(n);if(!e.ok)if(o&&typeof o[e.status]=="function")e=o[e.status].apply(e,n);else throw new Error(e.status+": "+e.statusText,{cause:e});return e}}var A=Object.assign({},P,{mw:{jsonmw:j,thrower:x}});globalThis.metro=A;var V=A;})(); +(()=>{var A=Object.defineProperty;var g=(n,o)=>{for(var e in o)A(n,e,{get:o[e],enumerable:!0})};var w={};g(w,{client:()=>L,formdata:()=>k,metroError:()=>f,request:()=>m,response:()=>b,trace:()=>E,url:()=>p});var d="https://metro.muze.nl/details/";Symbol.metroProxy||(Symbol.metroProxy=Symbol("isProxy"));Symbol.metroSource||(Symbol.metroSource=Symbol("source"));var l=class n{#e={url:typeof window<"u"?window.location:"https://localhost"};#t=["get","post","put","delete","patch","head","options","query"];static tracers={};constructor(...o){for(let e of o)if(typeof e=="string"||e instanceof String)this.#e.url=""+e;else if(e instanceof n)Object.assign(this.#e,e.#e);else if(e instanceof Function)this.#r([e]);else if(e&&typeof e=="object")for(let r in e)r=="middlewares"?this.#r(e[r]):typeof e[r]=="function"?this.#e[r]=e[r](this.#e[r],this.#e):this.#e[r]=e[r];this.#e.verbs&&(this.#t=this.#e.verbs,delete this.#e.verbs);for(let e of this.#t)this[e]=async function(...r){return this.fetch(m(this.#e,...r,{method:e.toUpperCase()}))};Object.freeze(this)}#r(o){typeof o=="function"&&(o=[o]);let e=o.findIndex(r=>typeof r!="function");if(e>=0)throw f("metro.client: middlewares must be a function or an array of functions "+d+"client/invalid-middlewares-value/",o[e]);Array.isArray(this.#e.middlewares)||(this.#e.middlewares=[]),this.#e.middlewares=this.#e.middlewares.concat(o)}fetch(o,e){if(o=m(o,e),!o.url)throw f("metro.client."+o.method.toLowerCase()+": Missing url parameter "+d+"client/missing-url-param/",o);if(e||(e={}),typeof e!="object"||Array.isArray(e)||e instanceof String)throw f("metro.client.fetch: Options is not an object");let t=[async function(i){i[Symbol.metroProxy]&&(i=i[Symbol.metroSource]);let u=await fetch(i);return b(u)}].concat(this.#e?.middlewares?.slice()||[]);e=Object.assign({},this.#e,e);let a;for(let s of t)a=function(i,u){return async function(j){let h,x=Object.values(n.tracers);for(let c of x)c.request&&c.request.call(c,j,u);h=await u(j,i);for(let c of x)c.response&&c.response.call(c,h,u);return h}}(a,s);return a(o)}with(...o){return new n(this,...o)}};function L(...n){return new l(...n)}function U(n,o){let e=o||{};!e.url&&o.url&&(e.url=o.url);for(let r of["method","headers","body","mode","credentials","cache","redirect","referrer","referrerPolicy","integrity","keepalive","signal","priority","url"]){let t=n[r];if(!(typeof t>"u"||t==null))if(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function")e[r]=t(e[r],e);else if(r=="url")e.url=p(e.url,t);else if(r=="headers"){e.headers=new Headers(o.headers),t instanceof Headers||(t=new Headers(n.headers));for(let[a,s]of t.entries())e.headers.set(a,s)}else e[r]=t}return n instanceof Request&&n.data&&(e.body=n.data),e}function m(...n){let o={url:typeof window<"u"?window.location:"https://localhost/",duplex:"half"};for(let t of n)typeof t=="string"||t instanceof URL||t instanceof URLSearchParams?o.url=p(o.url,t):t&&(t instanceof FormData||t instanceof ReadableStream||t instanceof Blob||t instanceof ArrayBuffer||t instanceof DataView)?o.body=t:t&&typeof t=="object"&&Object.assign(o,U(t,o));let e=o.body;e&&typeof e=="object"&&!(e instanceof String)&&!(e instanceof ReadableStream)&&!(e instanceof Blob)&&!(e instanceof ArrayBuffer)&&!(e instanceof DataView)&&!(e instanceof FormData)&&!(e instanceof URLSearchParams)&&(typeof TypedArray>"u"||!(e instanceof TypedArray))&&(o.body=JSON.stringify(e));let r=new Request(o.url,o);return Object.freeze(r),new Proxy(r,{get(t,a,s){switch(a){case Symbol.metroSource:return t;case Symbol.metroProxy:return!0;case"with":return function(...i){return e&&i.unshift({body:e}),m(t,...i)};case"body":break;case"data":return e}return t[a]instanceof Function?t[a].bind(t):t[a]}})}function v(n,o){let e=o||{};!e.url&&o.url&&(e.url=o.url);for(let r of["status","statusText","headers","body","url","type","redirected"]){let t=n[r];typeof t>"u"||t==null||(t?.[Symbol.metroProxy]&&(t=t[Symbol.metroSource]),typeof t=="function"?e[r]=t(e[r],e):r=="url"?e.url=new URL(t,e.url||"https://localhost/"):e[r]=t)}return n instanceof Response&&n.data&&(e.body=n.data),e}function b(...n){let o={};for(let t of n)typeof t=="string"?o.body=t:t instanceof Response?Object.assign(o,v(t,o)):t&&typeof t=="object"&&(t instanceof FormData||t instanceof Blob||t instanceof ArrayBuffer||t instanceof DataView||t instanceof ReadableStream||t instanceof URLSearchParams||t instanceof String||typeof TypedArray<"u"&&t instanceof TypedArray?o.body=t:Object.assign(o,v(t,o)));let e;o.body&&(e=o.body);let r=new Response(o.body,o);return Object.freeze(r),new Proxy(r,{get(t,a,s){switch(a){case Symbol.metroProxy:return!0;case Symbol.metroSource:return t;case"with":return function(...i){return b(t,...i)};case"data":return e;case"ok":return t.status>=200&&t.status<400}return typeof t[a]=="function"?t[a].bind(t):t[a]}})}function R(n,o){typeof o=="function"?o(n.searchParams,n):(o=new URLSearchParams(o),o.forEach((e,r)=>{n.searchParams.append(r,e)}))}function p(...n){let o=["hash","host","hostname","href","password","pathname","port","protocol","username","search","searchParams"],e=new URL("https://localhost/");for(let r of n)if(typeof r=="string"||r instanceof String)e=new URL(r,e);else if(r instanceof URL||typeof Location<"u"&&r instanceof Location)e=new URL(r);else if(r instanceof URLSearchParams)R(e,r);else if(r&&typeof r=="object")for(let t in r)if(t=="search")typeof r.search=="function"?r.search(e.search,e):e.search=new URLSearchParams(r.search);else if(t=="searchParams")R(e,r.searchParams);else{if(!o.includes(t))throw f("metro.url: unknown url parameter "+d+"url/unknown-param-name/",t);if(typeof r[t]=="function")r[t](e[t],e);else if(typeof r[t]=="string"||r[t]instanceof String||typeof r[t]=="number"||r[t]instanceof Number||typeof r[t]=="boolean"||r[t]instanceof Boolean)e[t]=""+r[t];else if(typeof r[t]=="object"&&r[t].toString)e[t]=r[t].toString();else throw f("metro.url: unsupported value for "+t+" "+d+"url/unsupported-param-value/",n[t])}else throw f("metro.url: unsupported option value "+d+"url/unsupported-option-value/",r);return Object.freeze(e),new Proxy(e,{get(r,t,a){switch(t){case Symbol.metroProxy:return!0;case Symbol.metroSource:return r;case"with":return function(...s){return p(r,...s)}}return r[t]instanceof Function?r[t].bind(r):r[t]}})}function k(...n){var o=new FormData;for(let e of n)if(e instanceof FormData)for(let r of e.entries())o.append(r[0],r[1]);else if(e&&typeof e=="object")for(let r of Object.entries(e))if(Array.isArray(r[1]))for(let t of r[1])o.append(r[0],t);else o.append(r[0],r[1]);else throw new f("metro.formdata: unknown option type, only FormData or Object supported",e);return Object.freeze(o),new Proxy(o,{get:(e,r,t)=>{switch(r){case Symbol.metroProxy:return!0;case Symbol.metroSource:return e;case"with":return function(...a){return k(e,...a)}}return e[r]instanceof Function?e[r].bind(e):e[r]}})}var y={error:(n,...o)=>{console.error("\u24C2\uFE0F ",n,...o)},info:(n,...o)=>{console.info("\u24C2\uFE0F ",n,...o)},group:n=>{console.group("\u24C2\uFE0F "+n)},groupEnd:n=>{console.groupEnd("\u24C2\uFE0F "+n)}};function f(n,...o){return y.error(n,...o),new Error(n,...o)}var E={add(n,o){l.tracers[n]=o},delete(n){delete l.tracers[n]},clear(){l.tracers={}},group(){let n=0;return{request:(o,e)=>{n++,y.group(n),y.info(o?.url,o,e)},response:(o,e)=>{y.info(o?.body?o.body[Symbol.metroSource]:null,o,e),y.groupEnd(n),n--}}}};function S(n){return n=Object.assign({reviver:null,replacer:null,space:""},n),async(o,e)=>{["POST","PUT","PATCH","QUERY"].includes(o.method)?(o=o.with({headers:{"Content-Type":"application/json",Accept:"application/json"}}),o.data&&typeof o.data=="object"&&!(o.data instanceof ReadableStream)&&(o=o.with({body:JSON.stringify(o.data,n.replacer,n.space)}))):o=o.with({headers:{Accept:"application/json"}});let r=await e(o),t=await r.text(),a=JSON.parse(t,n.reviver);return r.with({body:a})}}function P(n){return async(o,e)=>{let r=await e(o);if(!r.ok)if(n&&typeof n[r.status]=="function")r=n[r.status].apply(r,o);else throw new Error(r.status+": "+r.statusText,{cause:r});return r}}var O=Object.assign({},w,{mw:{jsonmw:S,thrower:P}});globalThis.metro=O;var N=O;})(); //# sourceMappingURL=everything.min.js.map diff --git a/dist/everything.min.js.map b/dist/everything.min.js.map index 0b3589c..484a944 100644 --- a/dist/everything.min.js.map +++ b/dist/everything.min.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/metro.mjs", "../src/mw/json.mjs", "../src/mw/thrower.mjs", "../src/everything.mjs"], - "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\t// even though a Proxy is supposed to be 'invisible'\n\t\t\t\t// fetch() doesn't work with the proxy (in Firefox), \n\t\t\t\t// you need the actual Request object here\n\t\t\t\t// and the actual body if you use e.g. FormData\n\t\t\t\tif (req.body && req.body[Symbol.metroSource]) {\n\t\t\t\t\tlet body = req.body[Symbol.metroSource]\n\t\t\t\t\treq = new Request(req[Symbol.metroSource], { body })\n\t\t\t\t} else {\n\t\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction bodyProxy(body, r)\n{\n\tlet source = r.body\n\tif (!source) {\n\t\t//Firefox does not allow access to Request.body (undefined)\n\t\t//Chrome and Nodejs do, so mimic the correct (documented)\n\t\t//result here\n\t\tif (body === null) {\n\t\t\tsource = new ReadableStream()\n\t\t} else if (body instanceof ReadableStream) {\n\t\t\tsource = body\n\t\t} else if (body instanceof Blob) {\n\t\t\tsource = body.stream()\n\t\t} else {\n\t\t\tsource = new ReadableStream({\n\t\t\t\tstart(controller) {\n\t\t\t\t\tlet chunk\n\t\t\t\t\tswitch(typeof body) {\n\t\t\t\t\t\tcase 'object':\n\t\t\t\t\t\t\tif (typeof body.toString == 'function') {\n\t\t\t\t\t\t\t\t// also catches URLSearchParams\n\t\t\t\t\t\t\t\tchunk = body.toString()\n\t\t\t\t\t\t\t} else if (body instanceof FormData) {\n\t\t\t\t\t\t\t\tchunk = new URLSearchParams(body).toString()\n\t\t\t\t\t\t\t} else if (body instanceof ArrayBuffer\n\t\t\t\t\t\t\t\t|| ArrayBuffer.isView(body)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// catchs TypedArrays - e.g. Uint16Array\n\t\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'string':\n\t\t\t\t\t\tcase 'number':\n\t\t\t\t\t\tcase 'boolean':\n\t\t\t\t\t\t\tchunk = body\n\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tthrow metroError('Cannot convert body to ReadableStream', body)\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcontroller.enqueue(chunk)\n\t\t\t\t\tcontroller.close()\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n\treturn new Proxy(source, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch (prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn body\n\t\t\t\tbreak\n\t\t\t\tcase 'toString':\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\treturn ''+body\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\tif (prop in body) {\n\t\t\t\t\tif (typeof body[prop] == 'function') {\n\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\treturn body[prop].apply(body, args)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn body[prop]\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t// and body may have its own toString\n\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn target[prop]\n\t\t\t}\n\t\t},\n\t\thas(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn prop in body\n\t\t\t} else {\n\t\t\t\treturn prop in target\n\t\t\t}\n\t\t},\n\t\townKeys(target) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Reflect.ownKeys(body)\n\t\t\t} else {\n\t\t\t\treturn Reflect.ownKeys(target)\n\t\t\t}\n\t\t},\n\t\tgetOwnPropertyDescriptor(target, prop) {\n\t\t\tif (body && typeof body == 'object') {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(body,prop)\n\t\t\t} else {\n\t\t\t\treturn Object.getOwnPropertyDescriptor(target,prop)\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet body = requestParams.body\n\tif (body) {\n\t\tif (typeof body == 'object'\n\t\t\t&& !(body instanceof String)\n\t\t\t&& !(body instanceof ReadableStream)\n\t\t\t&& !(body instanceof Blob)\n\t\t\t&& !(body instanceof ArrayBuffer)\n\t\t\t&& !(body instanceof DataView)\n\t\t\t&& !(body instanceof FormData)\n\t\t\t&& !(body instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(body instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(body)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (body) { // body is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// Request.body is always a ReadableStream\n\t\t\t\t\t// which is a horrible API, if you want to\n\t\t\t\t\t// allow middleware to alter the body\n\t\t\t\t\t// so we keep the original body, wrap a Proxy\n\t\t\t\t\t// around it to keep the ReadableStream api\n\t\t\t\t\t// accessible, but allow access to the original\n\t\t\t\t\t// body value as well\n\t\t\t\t\tif (!body) {\n\t\t\t\t\t\tbody = target.body\n\t\t\t\t\t}\n\t\t\t\t\tif (body) {\n\t\t\t\t\t\tif (body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(body, target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tvalue(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\tif (responseParams.body) {\n\t\t\t\t\t\tif (responseParams.body[Symbol.metroProxy]) {\n\t\t\t\t\t\t\treturn responseParams.body\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn bodyProxy(responseParams.body, target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn bodyProxy('',target)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t\tcase 'headers':\n\t\t\t\t\treturn target.headers\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (prop in responseParams && prop != 'toString') {\n\t\t\t\t\t\treturn responseParams[prop]\n\t\t\t\t\t}\n\t\t\t\t\tif (prop in target && prop != 'toString') {\n\t\t\t\t\t\t// skipped toString, since it has no usable output\n\t\t\t\t\t\t// and body may have its own toString\n\t\t\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\t\t\treturn function(...args) {\n\t\t\t\t\t\t\t\treturn target[prop].apply(target, args)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn undefined\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from '../metro.mjs'\n\nexport default function jsonmw(options) {\n\toptions = Object.assign({\n\t\treviver: null,\n\t\treplacer: null,\n\t\tspace: ''\n\t}, options)\n\n\treturn async (req, next) => {\n\t\tif (['POST','PUT','PATCH','QUERY'].includes(req.method)) {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type':'application/json',\n\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t\tif (req.body && typeof req.body[Symbol.metroSource] == 'object') {\n\t\t\t\treq = req.with({\n\t\t\t\t\tbody: JSON.stringify(req.body[Symbol.metroSource], options.replacer, options.space)\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tlet res = await next(req)\n\t\tlet body = await res.text()\n\t\tlet json = JSON.parse(body, options.reviver)\n\t\treturn res.with({\n\t\t\tbody: json\n\t\t})\n\t}\n}", "import * as metro from '../metro.mjs'\n\nexport default function thrower(options) {\n\n\treturn async (req, next) => {\n\t\tlet res = await next(req)\n\t\tif (!res.ok) {\n\t\t\tif (options && typeof options[res.status] == 'function') {\n\t\t\t\tres = options[res.status].apply(res, req)\n\t\t\t} else {\n\t\t\t\tthrow new Error(res.status+': '+res.statusText, {\n\t\t\t\t\tcause: res\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n}", "import * as m from './metro.mjs'\nimport jsonmw from './mw/json.mjs'\nimport thrower from './mw/thrower.mjs'\n\nconst metro = Object.assign({}, m, {\n\tmw: {\n\t\tjsonmw,\n\t\tthrower\n\t}\n})\n\nglobalThis.metro = metro\n\nexport default metro"], - "mappings": "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", - "names": ["metro_exports", "__export", "client", "formdata", "metroError", "request", "response", "trace", "url", "metroURL", "Client", "_Client", "#options", "#verbs", "options", "option", "#addMiddlewares", "param", "verb", "middlewares", "index", "m", "req", "body", "res", "next", "middleware", "tracers", "tracer", "bodyProxy", "body", "r", "source", "controller", "chunk", "metroError", "target", "prop", "receiver", "args", "getRequestParams", "req", "current", "params", "value", "url", "key", "val", "request", "options", "requestParams", "option", "getResponseParams", "res", "response", "responseParams", "appendSearchParams", "validParams", "u", "param", "metroURL", "formdata", "entry", "metroConsole", "message", "details", "name", "trace", "tracer", "Client", "group", "middleware", "jsonmw", "options", "req", "next", "res", "body", "json", "thrower", "options", "req", "next", "res", "metro", "metro_exports", "jsonmw", "thrower", "everything_default"] + "sourcesContent": ["/**\n * base URL used to link to more information about an error message\n */\nconst metroURL = 'https://metro.muze.nl/details/'\n\n/**\n * Symbols:\n * - isProxy: used to test if an object is a metro Proxy to another object\n * - source: used to return the actual source (target) of a metro Proxy\n */\nif (!Symbol.metroProxy) {\n\tSymbol.metroProxy = Symbol('isProxy')\n}\nif (!Symbol.metroSource) {\n\tSymbol.metroSource = Symbol('source')\n}\n\n/**\n * Metro HTTP Client with middleware support\n * @method get\n * @method post\n * @method put\n * @method delete\n * @method patch\n * @method head\n * @method options\n * @method query\n * @method fetch\n */\nclass Client\n{\n\t#options = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost'\n\t}\n\t#verbs = ['get','post','put','delete','patch','head','options','query']\n\n\tstatic tracers = {}\n\n\t/**\n\t * @typedef {Object} ClientOptions\n\t * @property {Array} middlewares - list of middleware functions\n\t * @property {string|URL} url - default url of the client\n\t * @property {[string]} verbs - a list of verb methods to expose, e.g. ['get','post']\n\t * \n\t * Constructs a new metro client. Can have any number of params.\n\t * @params {ClientOptions|URL|Function|Client}\n\t * @returns {Client} - A metro client object with given or default verb methods\n\t */\n\tconstructor(...options)\n\t{\n\t\tfor (let option of options) {\n\t\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t\tthis.#options.url = ''+option\n\t\t\t} else if (option instanceof Client) {\n\t\t\t\tObject.assign(this.#options, option.#options)\n\t\t\t} else if (option instanceof Function) {\n\t\t\t\tthis.#addMiddlewares([option])\n\t\t\t} else if (option && typeof option == 'object') {\n\t\t\t\tfor (let param in option) {\n\t\t\t\t\tif (param == 'middlewares') {\n\t\t\t\t\t\tthis.#addMiddlewares(option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.#options[param] = option[param](this.#options[param], this.#options)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.#options[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (this.#options.verbs) {\n\t\t\tthis.#verbs = this.#options.verbs\n\t\t\tdelete this.#options.verbs\n\t\t}\n\n\t\tfor (const verb of this.#verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.#options,\n\t\t\t\t\t...options,\n\t\t\t\t\t{method: verb.toUpperCase()}\n\t\t\t\t))\n\t\t\t}\n\t\t}\n\t\tObject.freeze(this)\n\t}\n\n\t#addMiddlewares(middlewares)\n\t{\n\t\tif (typeof middlewares == 'function') {\n\t\t\tmiddlewares = [ middlewares ]\n\t\t}\n\t\tlet index = middlewares.findIndex(m => typeof m != 'function')\n\t\tif (index>=0) {\n\t\t\tthrow metroError('metro.client: middlewares must be a function or an array of functions '\n\t\t\t\t+metroURL+'client/invalid-middlewares-value/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.#options.middlewares)) {\n\t\t\tthis.#options.middlewares = []\n\t\t}\n\t\tthis.#options.middlewares = this.#options.middlewares.concat(middlewares)\n\t}\n\n\t/**\n\t * Mimics the standard browser fetch method, but uses any middleware installed through\n\t * the constructor.\n\t * @param {Request|string|Object} - Required. The URL or Request object, accepts all types that are accepted by metro.request\n\t * @param {Object} - Optional. Any object that is accepted by metro.request\n\t * @return {Promise} - The metro.response to this request, or any other result as changed by any included middleware.\n\t */\n\tfetch(req, options)\n\t{\n\t\treq = request(req, options)\n\t\tif (!req.url) {\n\t\t\tthrow metroError('metro.client.'+req.method.toLowerCase()+': Missing url parameter '+metroURL+'client/missing-url-param/', req)\n\t\t}\n\t\tif (!options) {\n\t\t\toptions = {}\n\t\t}\n\t\tif (!(typeof options === 'object') \n\t\t\t|| Array.isArray(options)\n\t\t\t|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Options is not an object')\n\t\t}\n\n\t\tconst metrofetch = async function browserFetch(req)\n\t\t{\n\t\t\tif (req[Symbol.metroProxy]) {\n\t\t\t\treq = req[Symbol.metroSource]\n\t\t\t}\n\t\t\tconst res = await fetch(req)\n\t\t\treturn response(res)\n\t\t}\n\t\t\n\t\tlet middlewares = [metrofetch].concat(this.#options?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.#options, options)\n\t\t//@TODO: do this once in constructor?\n\t\tlet next\n\t\tfor (let middleware of middlewares) {\n\t\t\tnext = (function(next, middleware) {\n\t\t\t\treturn async function(req) {\n\t\t\t\t\tlet res\n\t\t\t\t\tlet tracers = Object.values(Client.tracers)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.request) {\n\t\t\t\t\t\t\ttracer.request.call(tracer, req, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tres = await middleware(req, next)\n\t\t\t\t\tfor(let tracer of tracers) {\n\t\t\t\t\t\tif (tracer.response) {\n\t\t\t\t\t\t\ttracer.response.call(tracer, res, middleware)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn res\n\t\t\t\t}\t\t\t\t\t\t\t\t\n\t\t\t})(next, middleware)\n\t\t}\n\t\treturn next(req)\n\t}\n\n\twith(...options) {\n\t\treturn new Client(this, ...options)\n\t}\n}\n\n/**\n * Returns a new metro Client object.\n * @param {...ClientOptions|string|URL}\n * @return Client\n */\nexport function client(...options)\n{\n\treturn new Client(...options)\n}\n\nfunction appendHeaders(r, headers)\n{\n\tif (!Array.isArray(headers)) {\n\t\theaders = [headers]\n\t}\n\theaders.forEach((header) => {\n\t\tif (typeof header == 'function') {\n\t\t\tlet result = header(r.headers, r)\n\t\t\tif (result) {\n\t\t\t\tif (!Array.isArray(result)) {\n\t\t\t\t\tresult = [result]\n\t\t\t\t}\n\t\t\t\theaders = headers.concat(result)\n\t\t\t}\n\t\t}\n\t})\n\theaders.forEach((header) => {\n\t\tObject.entries(header).forEach(([name,value]) => {\t\t\t\n\t\t\tr.headers.append(name, value)\n\t\t})\n\t})\n}\n\nfunction getRequestParams(req, current)\n{\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\t// function to fetch all relevant properties of a Request\n\tfor(let prop of ['method','headers','body','mode','credentials','cache','redirect',\n\t\t'referrer','referrerPolicy','integrity','keepalive','signal',\n\t\t'priority','url']) {\n\t\tlet value = req[prop]\n\t\tif (typeof value=='undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = url(params.url, value)\n\t\t\t} else if (prop == 'headers') {\n\t\t\t\tparams.headers = new Headers(current.headers)\n\t\t\t\tif (!(value instanceof Headers)) {\n\t\t\t\t\tvalue = new Headers(req.headers)\n\t\t\t\t}\n\t\t\t\tfor (let [key, val] of value.entries()) {\n\t\t\t\t\tparams.headers.set(key, val)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (req instanceof Request && req.data) {\n\t\t// Request.body is always transformed into ReadableStreem\n\t\t// metro.request.data is the original body passed to Request()\n\t\tparams.body = req.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Request} MetroRequest\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {} ...options - request options, handled in order\n * @return {MetroRequest} - a new metro Request object\n */\nexport function request(...options)\n{\n\t// the standard Request constructor is a minefield\n\t// so first gather all the options together into a single\n\t// javascript object, then set it in one go\n\tlet requestParams = {\n\t\turl: typeof window != 'undefined' ? window.location : 'https://localhost/',\n\t\tduplex: 'half' // required when setting body to ReadableStream, just set it here by default already\n\t}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string'\n\t\t\t|| option instanceof URL\n\t\t\t|| option instanceof URLSearchParams\n\t\t) {\n\t\t\trequestParams.url = url(requestParams.url, option)\n\t\t} else if (option && (\n\t\t\toption instanceof FormData\n\t\t\t|| option instanceof ReadableStream\n\t\t\t|| option instanceof Blob\n\t\t\t|| option instanceof ArrayBuffer\n\t\t\t|| option instanceof DataView\n\t\t)) {\n\t\t\trequestParams.body = option\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tObject.assign(requestParams, getRequestParams(option, requestParams))\n\t\t}\n\t}\n\tlet data = requestParams.body\n\tif (data) {\n\t\tif (typeof data == 'object'\n\t\t\t&& !(data instanceof String)\n\t\t\t&& !(data instanceof ReadableStream)\n\t\t\t&& !(data instanceof Blob)\n\t\t\t&& !(data instanceof ArrayBuffer)\n\t\t\t&& !(data instanceof DataView)\n\t\t\t&& !(data instanceof FormData)\n\t\t\t&& !(data instanceof URLSearchParams)\n\t\t\t&& (typeof TypedArray=='undefined' || !(data instanceof TypedArray))\n\t\t) {\n\t\t\trequestParams.body = JSON.stringify(data)\n\t\t}\n\t}\n\tlet r = new Request(requestParams.url, requestParams)\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\tif (data) { // data is kept in a seperate value, if it set earlier\n\t\t\t\t\t\t\toptions.unshift({ body: data }) // unshifted so it can be overridden by options\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn request(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'body':\n\t\t\t\t\t// FIXME: Firefox doesn't have Request.body\n\t\t\t\t\t// should we provide it here? metro.request.data\n\t\t\t\t\t// is a better alternative\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\tif (prop === 'clone') {\n\t\t\t\t\t// TODO: set req.data as the body of the clone\n\t\t\t\t}\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction getResponseParams(res, current)\n{\n\t// function to fetch all relevant properties of a Response\n\tlet params = current || {}\n\tif (!params.url && current.url) {\n\t\tparams.url = current.url\n\t}\n\tfor(let prop of ['status','statusText','headers','body','url','type','redirected']) {\n\t\tlet value = res[prop]\n\t\tif (typeof value == 'undefined' || value == null) {\n\t\t\tcontinue\n\t\t}\n\t\tif (value?.[Symbol.metroProxy]) {\n\t\t\tvalue = value[Symbol.metroSource]\n\t\t}\n\t\tif (typeof value == 'function') {\n\t\t\tparams[prop] = value(params[prop], params)\n\t\t} else {\n\t\t\tif (prop == 'url') {\n\t\t\t\tparams.url = new URL(value, params.url || 'https://localhost/')\n\t\t\t} else {\n\t\t\t\tparams[prop] = value\n\t\t\t}\n\t\t}\n\t}\n\tif (res instanceof Response && res.data) {\n\t\t// Response.body is always transformed into ReadableStreem FIXME: check this\n\t\t// metro.response.data is the original body passed to Response()\n\t\tparams.body = res.data\n\t}\n\treturn params\n}\n\n/**\n * @typedef {Response} MetroResponse\n * @property {Symbol(source)} - returns the target Response of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroResponse, with the given options added\n * @param {} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {} ...options - request options, handled in order\n * @return {MetroResponse} - a new metro Response object\n */\nexport function response(...options)\n{\n\tlet responseParams = {}\n\tfor (let option of options) {\n\t\tif (typeof option == 'string') {\n\t\t\tresponseParams.body = option\n\t\t} else if (option instanceof Response) {\n\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tif (option instanceof FormData\n\t\t\t\t|| option instanceof Blob\n\t\t\t\t|| option instanceof ArrayBuffer\n\t\t\t\t|| option instanceof DataView\n\t\t\t\t|| option instanceof ReadableStream\n\t\t\t\t|| option instanceof URLSearchParams\n\t\t\t\t|| option instanceof String\n\t\t\t\t|| (typeof TypedArray != 'undefined' && option instanceof TypedArray)\n\t\t\t) {\n\t\t\t\tresponseParams.body = option\n\t\t\t} else {\n\t\t\t\tObject.assign(responseParams, getResponseParams(option, responseParams))\n\t\t\t}\n\t\t}\n\t}\n\tlet data = undefined\n\tif (responseParams.body) {\n\t\tdata = responseParams.body\n\t}\n\tlet r = new Response(responseParams.body, responseParams)\t\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn response(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tcase 'data':\n\t\t\t\t\t// body is turned into ReadableStream\n\t\t\t\t\t// data is the original body param\n\t\t\t\t\treturn data\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\treturn (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params) {\n\tif (typeof params == 'function') {\n\t\t params(url.searchParams, url)\n\t} else {\n\t\tparams = new URLSearchParams(params)\n\t\tparams.forEach((value,key) => {\n\t\t\turl.searchParams.append(key, value)\n\t\t})\n\t}\n}\n\n/**\n * @typedef {URL} MetroURL\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {} ...options - url options, handled in order\n * @return {MetroURL} - a new metro URL object\n */\nexport function url(...options)\n{\n\tlet validParams = ['hash','host','hostname','href',\n\t\t\t'password','pathname','port','protocol','username','search','searchParams']\n\tlet u = new URL('https://localhost/')\n\tfor (let option of options) {\n\t\tif (typeof option == 'string' || option instanceof String) {\n\t\t\t// option is a relative or absolute url\n\t\t\tu = new URL(option, u)\n\t\t} else if (option instanceof URL \n\t\t\t|| (typeof Location != 'undefined' \n\t\t\t\t&& option instanceof Location)\n\t\t) {\n\t\t\tu = new URL(option)\n\t\t} else if (option instanceof URLSearchParams) {\n\t\t\tappendSearchParams(u, option)\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let param in option) {\n\t\t\t\tif (param=='search') {\n\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t}\n\t\t\t\t} else if (param=='searchParams') {\n\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t} else {\n\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t}\n\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t} else if (\n\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t) {\n\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow metroError('metro.url: unsupported value for '+param+' '+metroURL+'url/unsupported-param-value/', options[param])\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow metroError('metro.url: unsupported option value '+metroURL+'url/unsupported-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(u)\n\treturn new Proxy(u, {\n\t\tget(target, prop, receiver) {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn url(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\n/**\n * @typedef {FormData} MetroFormData\n * @property {Symbol(source)} - returns the target Request of this Proxy\n * @property {Symbol(isProxy)} - returns true\n * @method with - returns a new MetroRequest, with the given options added\n * @param {} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {} ...options - formdata options, handled in order\n * @return {MetroURL} - a new metro FormData object\n */\nexport function formdata(...options)\n{\n\tvar params = new FormData()\n\tfor (let option of options) {\n\t\tif (option instanceof FormData) {\n\t\t\tfor (let entry of option.entries()) {\n\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t}\n\t\t} else if (option && typeof option == 'object') {\n\t\t\tfor (let entry of Object.entries(option)) {\n\t\t\t\tif (Array.isArray(entry[1])) {\n\t\t\t\t\tfor (let value of entry[1]) {\n\t\t\t\t\t\tparams.append(entry[0], value)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tparams.append(entry[0],entry[1])\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new metroError('metro.formdata: unknown option type, only FormData or Object supported',option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget: (target,prop,receiver) => {\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\treturn true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\treturn target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\treturn function(...options) {\n\t\t\t\t\t\treturn formdata(target, ...options)\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\treturn target[prop].bind(target)\n\t\t\t}\n\t\t\treturn target[prop]\n\t\t}\n\t})\n}\n\nconst metroConsole = {\n\terror: (message, ...details) => {\n\t\tconsole.error('\u24C2\uFE0F ',message, ...details)\n\t},\n\tinfo: (message, ...details) => {\n\t\tconsole.info('\u24C2\uFE0F ',message, ...details)\n\t},\n\tgroup: (name) => {\n\t\tconsole.group('\u24C2\uFE0F '+name)\n\t},\n\tgroupEnd: (name) => {\n\t\tconsole.groupEnd('\u24C2\uFE0F '+name)\n\t}\n}\n\n\n/**\n * Custom Metro Error function that outputs to the console then throws an error\n */\nexport function metroError(message, ...details) {\n\tmetroConsole.error(message, ...details)\n\treturn new Error(message, ...details)\n}\n\n/**\n * Set of debugging tools to trace the request - response flow\n * Tracer are run on all metro fetch calls\n */\nexport const trace = {\n\t/**\n\t * Adds a named tracer function\n\t * @param {string} name - the name of the tracer\n\t * @param {Function} tracer - the tracer function to call\n\t */\n\tadd(name, tracer) {\n\t\tClient.tracers[name] = tracer\n\t},\n\t/**\n\t * Removes a named tracer function\n\t * @param {string} name\n\t */\n\tdelete(name) {\n\t\tdelete Client.tracers[name]\n\t},\n\t/**\n\t * Removes all tracer functions\n\t */\n\tclear() {\n\t\tClient.tracers = {}\n\t},\n\t/**\n\t * Returns a set of request and response tracer functions that use the\n\t * console.group feature to shows nested request/response pairs, with\n\t * most commonly needed information for debugging\n\t */\n\tgroup() {\n\t\tlet group = 0;\n\t\treturn {\n\t\t\trequest: (req, middleware) => {\n\t\t\t\tgroup++\n\t\t\t\tmetroConsole.group(group)\n\t\t\t\tmetroConsole.info(req?.url, req, middleware)\n\t\t\t},\n\t\t\tresponse: (res, middleware) => {\n\t\t\t\tmetroConsole.info(res?.body ? res.body[Symbol.metroSource]: null, res, middleware)\n\t\t\t\tmetroConsole.groupEnd(group)\n\t\t\t\tgroup--\n\t\t\t}\n\t\t}\n\t}\n}\n", "import * as metro from '../metro.mjs'\n\nexport default function jsonmw(options) {\n\toptions = Object.assign({\n\t\treviver: null,\n\t\treplacer: null,\n\t\tspace: ''\n\t}, options)\n\n\treturn async (req, next) => {\n\t\tif (['POST','PUT','PATCH','QUERY'].includes(req.method)) {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type':'application/json',\n\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t\tif (req.data && typeof req.data=='object' && !(req.data instanceof ReadableStream)) {\n\t\t\t\treq = req.with({\n\t\t\t\t\tbody: JSON.stringify(req.data, options.replacer, options.space)\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t 'Accept':'application/json'\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tlet res = await next(req)\n\t\tlet body = await res.text()\n\t\tlet json = JSON.parse(body, options.reviver)\n\t\treturn res.with({\n\t\t\tbody: json\n\t\t})\n\t}\n}", "import * as metro from '../metro.mjs'\n\nexport default function thrower(options) {\n\n\treturn async (req, next) => {\n\t\tlet res = await next(req)\n\t\tif (!res.ok) {\n\t\t\tif (options && typeof options[res.status] == 'function') {\n\t\t\t\tres = options[res.status].apply(res, req)\n\t\t\t} else {\n\t\t\t\tthrow new Error(res.status+': '+res.statusText, {\n\t\t\t\t\tcause: res\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n}", "import * as m from './metro.mjs'\nimport jsonmw from './mw/json.mjs'\nimport thrower from './mw/thrower.mjs'\n\nconst metro = Object.assign({}, m, {\n\tmw: {\n\t\tjsonmw,\n\t\tthrower\n\t}\n})\n\nglobalThis.metro = metro\n\nexport default metro"], + "mappings": "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", + "names": ["metro_exports", "__export", "client", "formdata", "metroError", "request", "response", "trace", "url", "metroURL", "Client", "_Client", "#options", "#verbs", "options", "option", "#addMiddlewares", "param", "verb", "middlewares", "index", "m", "req", "res", "next", "middleware", "tracers", "tracer", "getRequestParams", "req", "current", "params", "prop", "value", "url", "key", "val", "request", "options", "requestParams", "option", "data", "target", "receiver", "getResponseParams", "res", "response", "responseParams", "appendSearchParams", "validParams", "u", "param", "metroError", "metroURL", "formdata", "entry", "metroConsole", "message", "details", "name", "trace", "tracer", "Client", "group", "middleware", "jsonmw", "options", "req", "next", "res", "body", "json", "thrower", "options", "req", "next", "res", "metro", "metro_exports", "jsonmw", "thrower", "everything_default"] } diff --git a/docs/introduction.md b/docs/introduction.md index f9b479c..c49df88 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -20,7 +20,7 @@ const client = metro.client({ let response = await client.get('/repos/muze-nl/metro/commits') if (response.ok) { - for ( const commit of response.body ) { + for ( const commit of response.data ) { console.log(commit.commit.message) } } diff --git a/docs/middleware.md b/docs/middleware.md index 0e19a4c..306f085 100644 --- a/docs/middleware.md +++ b/docs/middleware.md @@ -13,9 +13,9 @@ See the [middleware documentation](./middleware/) for a list of default middlewa ## Creating middleware -A middleware is a function with (request, next) as parameters, returning a response. Both request and response adhere to the Fetch API Request and Response standard. +A middleware is a function with (request, next) as parameters, returning a response. Both request and response adhere to the Fetch API [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) standard. -next is a function that takes a request and returns a Promise. This function is defined by MetroJS and automatically passed to your middleware function. The idea is that your middleware function can change the request and pass it on to the next middleware or the actual fetch() call, then intercept the response and change that and return it: +next is a function that takes a request and returns a `Promise`. This function is defined by MetroJS and automatically passed to your middleware function. The idea is that your middleware function can change the request and pass it on to the next middleware or the actual `fetch()` call, then intercept the response and change that and return it: ```javascript async function myMiddleware(req,next) { @@ -28,5 +28,23 @@ async function myMiddleware(req,next) { } ``` -/Note/: Both request and response have a with function. This allows you to create a new request or response, from the existing one, with one or more options added or changed. The original request or response is not changed. See the [reference]() for more information. +/Note/: Both `metro.request` and `metro.response` have a with function. This allows you to create a new request or response, from the existing one, with one or more options added or changed. The original request or response is not changed. See the [reference](./reference/) for more information. +## Differences to the browser Request and Response objects + +The browsers `Request` and `Response` classes were never designed with middleware in mind. The consequence is that some things have been altered in `metro.request()` and `metro.response()`. Most notably the handling of `Request.body` and `Response.body`. + +In a normal `Request` and `Response`, the moment that you set a body, the body is transformed into a `ReadableStream`. Streams can only be read asynchronously, and only once. This is clearly not suitable for a middleware function, where you would want to inspect the current body, and possibly alter it. + +So in a `metro.request` or a `metro.response`, if you set a new body, the original body parameter that you passed to it, is stored as `request.data` or `response.data`. `metro.request().body` and `metro.response().body` are still `ReadableStreams`, and work like normal. But now if you pass a `FormData` or `URLSearchParams` object as a body, you can still access them in `metro.request().data` or `metro.response().data`. + +To do this, the `metro.request()` and `metro.response()` functions return a Proxy to the Request and Response objects. However, `fetch()` (the default browser implementation) will not accept Proxies as parameter. So `metro.client().fetch()`unwraps the Proxies for you. + +These Proxies also allow you to do specific metro things, like: +```javascript + let req = metro.request('https://example.com', new URLSearchParams('?foo=bar')) + req = req.with({searchParams: {'foo2':'bar'}}) + console.log(req.data.get('foo2')) +``` + +See the [issues](./issues.md) for a list of issues with the normal Fetch API that metro fixes, or at least makes simpler. \ No newline at end of file diff --git a/docs/reference/request/README.md b/docs/reference/request/README.md index 6de1594..b1ad10b 100644 --- a/docs/reference/request/README.md +++ b/docs/reference/request/README.md @@ -14,7 +14,7 @@ If you enter a string as option, it will always be interpreted as a URL. Just li let req = metro.request('https://example.com/') ``` -## default request methods +## default Request methods - [`arrayBuffer()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/arrayBuffer) - [`blob()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/blob) @@ -23,6 +23,10 @@ let req = metro.request('https://example.com/') - [`json()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/json) - [`text()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/text) -## metro request methods +## metro Request methods -- [`with()`](./with.md) \ No newline at end of file +- [`with()`](./with.md) + +## metro Request properties + +- [`data`](./data.md) diff --git a/docs/reference/request/data.md b/docs/reference/request/data.md new file mode 100644 index 0000000..86ce1d1 --- /dev/null +++ b/docs/reference/request/data.md @@ -0,0 +1,13 @@ +# request.data + +``` +let res = metro.request({ + method: 'POST', + body: { + foo: 'bar' + } +}) +console.log(res.data) // prints { foo: "bar" } +``` + +Whenever you set a body on a request, you can later access the original body parameter as `request.data`. If you access `request.body`, you will see that it is transformed into a ReadableStream, which can only be read once. The metro.request() function adds the `data` property. diff --git a/docs/reference/request/with.md b/docs/reference/request/with.md new file mode 100644 index 0000000..ef9dbef --- /dev/null +++ b/docs/reference/request/with.md @@ -0,0 +1,7 @@ +# request.with + +``` +request.with(...options) : Request +``` + +The `with()` method creates a new metro request, with all the overrides set in the `...options` parameters. It accepts the same options as the [`metro.request()`](./README.md) method does. \ No newline at end of file diff --git a/docs/reference/response/README.md b/docs/reference/response/README.md index bed8147..873bc54 100644 --- a/docs/reference/response/README.md +++ b/docs/reference/response/README.md @@ -8,18 +8,18 @@ Returns a new response, built out of the options passed. Later option values ove Unlike the normal Response, you can set all available properties for a response, except `ok`. That is automatically derived from the status code. -You can set the body to any supported type, and additionally to a normal Object. The body will still report as a ReadableStream, but you can iterate over it like it was just a normal Object. e.g: +You can set the body to any supported type, or to a plain Object. The body will still report as a ReadableStream, but now you can access `response.data`, which will be the object passed as the body parameter. e.g: ```javascript const res = metro.response({ status: 200, statusText: 'OK', body: { - data: 'some data' + foo: 'some data' } }) -const data = res.body.data +const data = res.data.foo ``` Creating responses from scratch is not usually needed, except when creating mock responses for testing or when enhancing responses in a middleware component. In that case the [`with()`](./with.md) comes in handy. @@ -35,4 +35,8 @@ Creating responses from scratch is not usually needed, except when creating mock ## metro Response methods -- [`with()`](./with.md) \ No newline at end of file +- [`with()`](./with.md) + +## metro Response properties + +- [`data`](./data.md) \ No newline at end of file diff --git a/docs/reference/response/data.md b/docs/reference/response/data.md new file mode 100644 index 0000000..ec3ccf6 --- /dev/null +++ b/docs/reference/response/data.md @@ -0,0 +1,13 @@ +# response.data + +``` +let res = metro.response({ + method: 'POST', + body: { + foo: 'bar' + } +}) +console.log(res.data) // prints { foo: "bar" } +``` + +Whenever you set a body on a Response, you can later access the original body parameter as `response.data`. If you access `response.body`, you will see that it is transformed into a ReadableStream, which can only be read once. The metro.response() function adds the `data` property. diff --git a/package.json b/package.json index e90ab6c..e5cd254 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@muze-nl/metro", - "version": "0.5.5", + "version": "0.6.0", "description": "http client with middleware support", "type": "module", "source": [ "src/browser.mjs", "src/everything.mjs" ], diff --git a/src/metro.mjs b/src/metro.mjs index 3974340..284fe74 100644 --- a/src/metro.mjs +++ b/src/metro.mjs @@ -25,6 +25,7 @@ if (!Symbol.metroSource) { * @method head * @method options * @method query + * @method fetch */ class Client { @@ -125,16 +126,7 @@ class Client const metrofetch = async function browserFetch(req) { if (req[Symbol.metroProxy]) { - // even though a Proxy is supposed to be 'invisible' - // fetch() doesn't work with the proxy (in Firefox), - // you need the actual Request object here - // and the actual body if you use e.g. FormData - if (req.body && req.body[Symbol.metroSource]) { - let body = req.body[Symbol.metroSource] - req = new Request(req[Symbol.metroSource], { body }) - } else { - req = req[Symbol.metroSource] - } + req = req[Symbol.metroSource] } const res = await fetch(req) return response(res) @@ -205,114 +197,6 @@ function appendHeaders(r, headers) }) } -function bodyProxy(body, r) -{ - let source = r.body - if (!source) { - //Firefox does not allow access to Request.body (undefined) - //Chrome and Nodejs do, so mimic the correct (documented) - //result here - if (body === null) { - source = new ReadableStream() - } else if (body instanceof ReadableStream) { - source = body - } else if (body instanceof Blob) { - source = body.stream() - } else { - source = new ReadableStream({ - start(controller) { - let chunk - switch(typeof body) { - case 'object': - if (typeof body.toString == 'function') { - // also catches URLSearchParams - chunk = body.toString() - } else if (body instanceof FormData) { - chunk = new URLSearchParams(body).toString() - } else if (body instanceof ArrayBuffer - || ArrayBuffer.isView(body) - ) { - // catchs TypedArrays - e.g. Uint16Array - chunk = body - } else { - throw metroError('Cannot convert body to ReadableStream', body) - } - break - case 'string': - case 'number': - case 'boolean': - chunk = body - break - default: - throw metroError('Cannot convert body to ReadableStream', body) - break - } - controller.enqueue(chunk) - controller.close() - } - }) - } - } - return new Proxy(source, { - get(target, prop, receiver) { - switch (prop) { - case Symbol.metroProxy: - return true - break - case Symbol.metroSource: - return body - break - case 'toString': - return function() { - return ''+body - } - break - } - if (body && typeof body == 'object') { - if (prop in body) { - if (typeof body[prop] == 'function') { - return function(...args) { - return body[prop].apply(body, args) - } - } - return body[prop] - } - } - if (prop in target && prop != 'toString') { - // skipped toString, since it has no usable output - // and body may have its own toString - if (typeof target[prop] == 'function') { - return function(...args) { - return target[prop].apply(target, args) - } - } - return target[prop] - } - }, - has(target, prop) { - if (body && typeof body == 'object') { - return prop in body - } else { - return prop in target - } - }, - ownKeys(target) { - if (body && typeof body == 'object') { - return Reflect.ownKeys(body) - } else { - return Reflect.ownKeys(target) - } - }, - getOwnPropertyDescriptor(target, prop) { - if (body && typeof body == 'object') { - return Object.getOwnPropertyDescriptor(body,prop) - } else { - return Object.getOwnPropertyDescriptor(target,prop) - } - } - }) -} - function getRequestParams(req, current) { let params = current || {} @@ -331,7 +215,7 @@ function getRequestParams(req, current) value = value[Symbol.metroSource] } if (typeof value == 'function') { - value(params[prop], params) + params[prop] = value(params[prop], params) } else { if (prop == 'url') { params.url = url(params.url, value) @@ -348,6 +232,11 @@ function getRequestParams(req, current) } } } + if (req instanceof Request && req.data) { + // Request.body is always transformed into ReadableStreem + // metro.request.data is the original body passed to Request() + params.body = req.data + } return params } @@ -391,19 +280,19 @@ export function request(...options) Object.assign(requestParams, getRequestParams(option, requestParams)) } } - let body = requestParams.body - if (body) { - if (typeof body == 'object' - && !(body instanceof String) - && !(body instanceof ReadableStream) - && !(body instanceof Blob) - && !(body instanceof ArrayBuffer) - && !(body instanceof DataView) - && !(body instanceof FormData) - && !(body instanceof URLSearchParams) - && (typeof TypedArray=='undefined' || !(body instanceof TypedArray)) + let data = requestParams.body + if (data) { + if (typeof data == 'object' + && !(data instanceof String) + && !(data instanceof ReadableStream) + && !(data instanceof Blob) + && !(data instanceof ArrayBuffer) + && !(data instanceof DataView) + && !(data instanceof FormData) + && !(data instanceof URLSearchParams) + && (typeof TypedArray=='undefined' || !(data instanceof TypedArray)) ) { - requestParams.body = JSON.stringify(body) + requestParams.body = JSON.stringify(data) } } let r = new Request(requestParams.url, requestParams) @@ -419,32 +308,25 @@ export function request(...options) break case 'with': return function(...options) { - if (body) { // body is kept in a seperate value, if it set earlier - options.unshift({ body }) // unshifted so it can be overridden by options + if (data) { // data is kept in a seperate value, if it set earlier + options.unshift({ body: data }) // unshifted so it can be overridden by options } return request(target, ...options) } break case 'body': - // Request.body is always a ReadableStream - // which is a horrible API, if you want to - // allow middleware to alter the body - // so we keep the original body, wrap a Proxy - // around it to keep the ReadableStream api - // accessible, but allow access to the original - // body value as well - if (!body) { - body = target.body - } - if (body) { - if (body[Symbol.metroProxy]) { - return body - } - return bodyProxy(body, target) - } + // FIXME: Firefox doesn't have Request.body + // should we provide it here? metro.request.data + // is a better alternative + break + case 'data': + return data break } if (target[prop] instanceof Function) { + if (prop === 'clone') { + // TODO: set req.data as the body of the clone + } return target[prop].bind(target) } return target[prop] @@ -468,7 +350,7 @@ function getResponseParams(res, current) value = value[Symbol.metroSource] } if (typeof value == 'function') { - value(params[prop], params) + params[prop] = value(params[prop], params) } else { if (prop == 'url') { params.url = new URL(value, params.url || 'https://localhost/') @@ -477,6 +359,11 @@ function getResponseParams(res, current) } } } + if (res instanceof Response && res.data) { + // Response.body is always transformed into ReadableStreem FIXME: check this + // metro.response.data is the original body passed to Response() + params.body = res.data + } return params } @@ -517,6 +404,10 @@ export function response(...options) } } } + let data = undefined + if (responseParams.body) { + data = responseParams.body + } let r = new Response(responseParams.body, responseParams) Object.freeze(r) return new Proxy(r, { @@ -533,39 +424,19 @@ export function response(...options) return response(target, ...options) } break - case 'body': - if (responseParams.body) { - if (responseParams.body[Symbol.metroProxy]) { - return responseParams.body - } - return bodyProxy(responseParams.body, target) - } else { - return bodyProxy('',target) - } + case 'data': + // body is turned into ReadableStream + // data is the original body param + return data break case 'ok': return (target.status>=200) && (target.status<400) break - case 'headers': - return target.headers - break - default: - if (prop in responseParams && prop != 'toString') { - return responseParams[prop] - } - if (prop in target && prop != 'toString') { - // skipped toString, since it has no usable output - // and body may have its own toString - if (typeof target[prop] == 'function') { - return function(...args) { - return target[prop].apply(target, args) - } - } - return target[prop] - } - break } - return undefined + if (typeof target[prop] == 'function') { + return target[prop].bind(target) + } + return target[prop] } }) } diff --git a/src/mw/json.mjs b/src/mw/json.mjs index 852a31f..4752107 100644 --- a/src/mw/json.mjs +++ b/src/mw/json.mjs @@ -15,9 +15,9 @@ export default function jsonmw(options) { 'Accept':'application/json' } }) - if (req.body && typeof req.body[Symbol.metroSource] == 'object') { + if (req.data && typeof req.data=='object' && !(req.data instanceof ReadableStream)) { req = req.with({ - body: JSON.stringify(req.body[Symbol.metroSource], options.replacer, options.space) + body: JSON.stringify(req.data, options.replacer, options.space) }) } } else { diff --git a/test/client.mjs b/test/client.mjs index 60baca3..357a248 100644 --- a/test/client.mjs +++ b/test/client.mjs @@ -37,7 +37,7 @@ tap.test('withFunction', async t => { let c = metro.client() c = c.with((req,next) => metro.response('This is the body')) let res = await c.get('foo/') - t.equal(''+res.body, 'This is the body') + t.equal(''+res.data, 'This is the body') t.end() }) @@ -52,12 +52,12 @@ tap.test('tracers', async t => { let res = await c.get('foo/') t.equal(trace.length, 1) t.equal(trace[0].request.url, 'https://localhost/foo/') - t.equal(''+trace[0].response.body, 'This is the body') - t.equal(''+res.body, 'This is the body') + t.equal(''+trace[0].response.data, 'This is the body') + t.equal(''+res.data, 'This is the body') t.end() }) -tap.test('govert', async t => { +tap.test('post body', async t => { let url = 'http://localhost:3000/query/' let client = metro.client(url).with(echomw()) let response = await client.post({body:'foo'}) diff --git a/test/json.mjs b/test/json.mjs index 8efee7e..af3c16a 100644 --- a/test/json.mjs +++ b/test/json.mjs @@ -12,7 +12,7 @@ tap.test('start', async t => { } }) let res = await c.post(req) - t.equal(res.body.foo, 'bar') + t.equal(res.data.foo, 'bar') t.end() }) @@ -23,6 +23,6 @@ tap.test('start', async t => { foo: 'bar' } }) - t.equal(res.body.foo, 'bar') + t.equal(res.data.foo, 'bar') t.end() }) diff --git a/test/request.mjs b/test/request.mjs index 6439ee0..9f8b5df 100644 --- a/test/request.mjs +++ b/test/request.mjs @@ -73,7 +73,7 @@ tap.test('body', t => { method: 'POST', body: 'This is the body' }) - t.equal(''+req.body, 'This is the body') + t.equal(''+req.data, 'This is the body') t.end() }) @@ -85,8 +85,8 @@ tap.test('bodyFormData', t => { body: fd }) t.ok(req.body instanceof ReadableStream) - t.ok(req.body[Symbol.metroSource] instanceof FormData) - t.equal(req.body.get('foo'), 'bar') + t.ok(req.data instanceof FormData) + t.equal(req.data.get('foo'), 'bar') t.end() }) @@ -97,8 +97,8 @@ tap.test('inferBodyFromType', t => { method: 'POST' }, fd) t.ok(req.body instanceof ReadableStream) - t.ok(req.body[Symbol.metroSource] instanceof FormData) - t.equal(req.body.get('foo'), 'bar') + t.ok(req.data instanceof FormData) + t.equal(req.data.get('foo'), 'bar') t.end() }) @@ -111,10 +111,10 @@ tap.test('bodyObject', t => { body: body }) t.ok(req.body instanceof ReadableStream) - t.equal(req.body.foo, 'bar') - t.ok('foo' in req.body) - t.ok(Object.prototype.hasOwnProperty.call(req.body,'foo')) - t.ok(req.body.hasOwnProperty('foo')) + t.equal(req.data.foo, 'bar') + t.ok('foo' in req.data) + t.ok(Object.prototype.hasOwnProperty.call(req.data,'foo')) + t.ok(req.data.hasOwnProperty('foo')) t.end() }) @@ -125,7 +125,7 @@ tap.test('bodyString', t => { body: body }) t.ok(req.body instanceof ReadableStream) - t.equal(req.body+'', 'bar') + t.equal(req.data+'', 'bar') t.end() }) @@ -146,10 +146,10 @@ tap.test('bodyFunction', t => { body: 'This is the body' }, { body: (b, r) => { - r.body = b+' altered' + return b+' altered' } }) - t.equal(''+req.body, 'This is the body altered') + t.equal(''+req.data, 'This is the body altered') t.end() }) diff --git a/test/response.mjs b/test/response.mjs index 5c0b07a..1a5883c 100644 --- a/test/response.mjs +++ b/test/response.mjs @@ -3,7 +3,7 @@ import * as metro from '../src/metro.mjs' tap.test('start', t => { let res = metro.response('body') - t.equal(''+res.body, 'body') + t.equal(''+res.data, 'body') t.end() }) @@ -16,7 +16,7 @@ tap.test('copy', t => { }) t.equal(res.status, 200) t.equal(res2.status, 201) - t.equal(''+res2.body, 'body') + t.equal(''+res2.data, 'body') t.end() }) @@ -40,9 +40,7 @@ tap.test('bodyFormData', t => { fd.append('foo','bar') let res = metro.response(fd) t.ok(res.body instanceof ReadableStream) - t.ok(res.body[Symbol.metroProxy]) - let x = res.body.get('foo') - t.equal(res.body.get('foo'), 'bar') + t.equal(res.data.get('foo'), 'bar') t.end() }) @@ -57,10 +55,10 @@ tap.test('bodyReadableStream', async t => { tap.test('bodyFunction', t => { let res = metro.response('This is the body', { body: (b, r) => { - r.body = b+' altered' + return b+' altered' } }) - t.equal(''+res.body, 'This is the body altered') + t.equal(''+res.data, 'This is the body altered') t.end() })