@muze-nl/jsfs-solid 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../node_modules/@muze-nl/jsfs/src/Path.js", "../node_modules/@muze-nl/jsfs/src/Adapters/HttpAdapter.js", "../node_modules/@muze-nl/metro/src/metro.mjs", "../node_modules/@muze-nl/metro/src/mw/getdata.mjs", "../node_modules/@muze-nl/metro/src/mw/json.mjs", "../node_modules/@muze-nl/metro/src/mw/thrower.mjs", "../node_modules/@muze-nl/metro/src/api.mjs", "../node_modules/@muze-nl/metro/src/everything.mjs", "../node_modules/@muze-nl/assert/src/assert.mjs", "../node_modules/@muze-nl/metro-oauth2/src/tokenstore.mjs", "../node_modules/@muze-nl/metro-oauth2/src/oauth2.mjs", "../node_modules/@muze-nl/metro-oauth2/src/keysstore.mjs", "../node_modules/dpop/build/index.js", "../node_modules/@muze-nl/metro-oauth2/src/oauth2.dpop.mjs", "../node_modules/@muze-nl/metro-oidc/src/oidc.util.mjs", "../node_modules/@muze-nl/metro-oidc/src/oidc.discovery.mjs", "../node_modules/@muze-nl/metro-oidc/src/oidc.register.mjs", "../node_modules/@muze-nl/metro-oidc/src/oidc.store.mjs", "../node_modules/@muze-nl/metro-oidc/src/oidcmw.mjs", "../node_modules/@muze-nl/metro-oidc/src/browser.mjs", "../node_modules/@muze-nl/oldm/src/oldm.mjs", "../node_modules/@muze-nl/metro-oldm/src/oldmmw.mjs", "../node_modules/@muze-nl/metro-oldm/src/index.mjs", "../node_modules/@muze-nl/jaqt/src/jaqt.mjs", "../src/SolidAdapter.js", "../src/browser.js"],
4
+ "sourcesContent": ["export default class Path {\n #value;\n\n constructor(path) {\n this.#value = Path.collapse(path);\n }\n\n get value() {\n return this.#value;\n }\n\n toString() {\n return this.#value;\n }\n\n get length() {\n return this.#value.length;\n }\n\n static collapse(path, cwd='') {\n if (path instanceof Path) {\n return path.value;\n }\n if (typeof path !== 'string' ) {\n throw new TypeError('path argument must be a string or an instance of Path');\n }\n if (cwd && !(cwd instanceof Path)) {\n cwd = new Path(cwd);\n }\n path = path.trim();\n if (path.length===0) {\n return cwd.value;\n }\n if (Path.isRelative(path)) {\n path = cwd+path;\n }\n let pathnames = Path.reduce(path, (result, entry) => {\n if (entry == '..' ) {\n result.pop();\n } else if (entry !== '.') {\n result.push(entry);\n }\n return result;\n }, []);\n let result = '/';\n if (pathnames.length) {\n result += pathnames.join('/');\n if (Path.isFolder(path)) {\n result += '/';\n }\n }\n return result;\n }\n\n static isAbsolute(path) {\n if (path instanceof Path) {\n return true;\n }\n return path.length && path[0]==='/';\n }\n\n static isRelative(path) {\n return !Path.isAbsolute(path); \n }\n\n static isFolder(path) {\n if (path instanceof Path) {\n path = path.value;\n }\n return path.length && path[path.length-1] == '/';\n }\n\n static isPath(path) {\n if (path instanceof Path) {\n return true;\n }\n if (typeof path !== 'string') {\n return false;\n }\n path = path.trim();\n let u = new URL(path, document.location);\n return u.pathname == path;\n }\n\n static reduce(path, reducer, initial) {\n if (path instanceof Path) {\n path = path.value;\n }\n return path.split('/').filter(Boolean).reduce(reducer, initial);\n }\n\n static map(path, callback) {\n if (path instanceof Path) {\n path = path.value;\n }\n return path.split('/').filter(Boolean).map(callback);\n }\n\n static parent(path) {\n if (path instanceof Path) {\n path = path.value;\n }\n path = path.split('/').filter(Boolean);\n path.pop();\n let result = '/';\n if (path.length) {\n result += path.join('/')+'/';\n }\n return result;\n }\n\n static filename(path) {\n if (path instanceof Path) {\n path = path.value;\n }\n return path.split('/').filter(Boolean).pop();\n }\n \n static head(path) {\n if (path instanceof Path) {\n path = path.value;\n }\n return path.split('/').filter(Boolean).shift();\n }\n \n static tail(path) {\n if (path instanceof Path) {\n path = path.value;\n }\n path = path.split('/').filter(Boolean)\n path.shift();\n let result = '/';\n if (path.length) {\n result += path.join('/')+'/';\n }\n return result;\n }\n}", "import Path from '../Path.js';\n\nexport default class HttpAdapter {\n \n #baseUrl;\n #path;\n #exceptionHandler;\n #fetchParams;\n\n constructor(baseUrl, path='/', exceptionHandler=null, fetchParams={}) {\n this.#baseUrl = new URL(baseUrl, window.location.href);\n this.#path = new Path(path);\n this.#exceptionHandler = exceptionHandler;\n this.#fetchParams = fetchParams;\n }\n\n get name() {\n return 'HttpAdapter';\n }\n\n get path() {\n return this.#path;\n }\n\n supportsWrite() {\n return true;\n }\n\n supportsStreamingWrite() {\n return supportsRequestStreams;\n }\n\n supportsStreamingRead() {\n return true;\n }\n\n cd(path) {\n if (!Path.isPath(path)) {\n throw new TypeError(path+' is not a valid path');\n }\n return new HttpAdapter(this.#baseUrl.href, path);\n }\n\n //FIXME: return a jsfs result object instead of http response\n async write(path, contents, metadata=null) {\n let params = Object.assign({}, this.#fetchParams, {\n method: 'PUT',\n body: contents\n });\n return this.#fetch(path, params);\n }\n\n writeStream(path, writer, metadata=null) {\n throw new Error('Not yet implemented')\n }\n\n async read(path) {\n let params = Object.assign({}, this.#fetchParams, {\n method: 'GET'\n });\n let response = await this.#fetch(path, params);\n //TODO: create a special jsfsFile class\n //with a toString that returns the contents\n //or better: mimic the File class of the browser\n let result = {\n type: this.#getMimetype(response),\n name: Path.filename(path),\n http: {\n headers: response.headers,\n status: response.status,\n url: response.url\n }\n }\n if (result.type.match(/text\\/.*/)) {\n result.contents = await response.text()\n } else if (result.type.match(/application\\/json.*/)) {\n result.contents = await response.json()\n } else {\n result.contents = await response.blob()\n }\n return result\n }\n\n readStream(path, reader) {\n throw new Error('Not yet implemented')\n }\n\n async exists(path) {\n let params = Object.assign({}, this.#fetchParams, {\n method: 'HEAD'\n });\n return this.#fetch(path, params);\n }\n\n async delete(path) {\n let params = Object.assign({}, this.#fetchParams, {\n method: 'DELETE'\n });\n return this.#fetch(path, params);\n }\n\n async list(path) {\n let supportedContentTypes = [\n 'text/html','text/xhtml','text/xhtml+xml','text/xml'\n ];\n let result = await this.read(path)\n if (supportedContentTypes.includes(result.type.split(';')[0])) {\n var html = result.contents\n } else {\n let url = this.#getUrl(path);\n throw new TypeError('URL '+url+' is not of a supported content type', {\n cause: result\n }); \n }\n\n let basePath = Path.collapse(this.#baseUrl.pathname);\n let parentUrl = this.#getUrl(path);\n // TODO: use DOMParser() directly here\n let dom = document.createElement('template');\n dom.innerHTML = html;\n let links = dom.content.querySelectorAll('a[href]');\n\n return Array.from(links)\n .map(link => {\n // use getAttribute to get the unchanged href value\n // otherwise relative hrefs will be turned into absolute values relative to the current window.location\n // instead of the path used in list()\n let url = new URL(link.getAttribute('href'), parentUrl.href); \n link.href = url.href;\n return {\n filename: Path.filename(link.pathname),\n path: link.pathname,\n name: link.innerText,\n href: link.href\n }\n })\n .filter(link => {\n // show only links that have the current URL as direct parent\n let testURL = new URL(link.href)\n testURL.pathname = Path.parent(testURL.pathname);\n return testURL.href===parentUrl.href;\n })\n .map(link => {\n return {\n filename: link.filename,\n path: link.path.substring(basePath.length-1), //TODO: Path.collapse() now always adds a trailing '/', so this works, but the added trailing / is probably not correct\n name: link.name\n }\n })\n }\n\n #getUrl(path) {\n path = Path.collapse(this.#baseUrl.pathname + Path.collapse(path));\n return new URL(path, this.#baseUrl);\n }\n\n async #fetch(path, options) {\n return fetch(this.#getUrl(path), options)\n .catch(e => {\n if (!this.#exceptionHandler || !this.#exceptionHandler(url, options, e)) {\n throw e;\n }\n })\n }\n\n #getMimetype(response) {\n if (response.headers.has('Content-Type')) {\n return response.headers.get('Content-Type')\n } else {\n return null\n }\n }\n}\n\nconst supportsRequestStreams = (async () => {\n const supportsStreamsInRequestObjects = !new Request(\n '', \n {\n body: new ReadableStream(),\n method: 'POST',\n duplex: 'half' // required in chrome\n }\n )\n .headers.has('Content-Type');\n\n if (!supportsStreamsInRequestObjects) {\n return false;\n }\n\n return fetch(\n 'data:a/a;charset=utf-8,', \n {\n method: 'POST',\n body: new ReadableStream(),\n duplex: 'half'\n }\n )\n .then(() => true, () => false);\n})();", "/**\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 */\nexport class Client\n{\n\tclientOptions = {\n\t\turl: typeof window != 'undefined' ? url(window.location) : url('https://localhost'),\n\t\tverbs: ['get','post','put','delete','patch','head','options','query']\n\t}\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.clientOptions.url = url(this.clientOptions.url.href, option)\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 (param == 'url') {\n\t\t\t\t\t\tthis.clientOptions.url = url(this.clientOptions.url.href, option[param])\n\t\t\t\t\t} else if (typeof option[param] == 'function') {\n\t\t\t\t\t\tthis.clientOptions[param] = option[param](this.clientOptions[param], this.clientOptions)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.clientOptions[param] = option[param]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const verb of this.clientOptions.verbs) {\n\t\t\tthis[verb] = async function(...options) {\n\t\t\t\treturn this.fetch(request(\n\t\t\t\t\tthis.clientOptions,\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\t//NOTE: intentionally not Object.freeze()-ing this, so that metro.api can extend this class\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/', middlewares[index])\n\t\t}\n\t\tif (!Array.isArray(this.clientOptions.middlewares)) {\n\t\t\tthis.clientOptions.middlewares = []\n\t\t}\n\t\tthis.clientOptions.middlewares = this.clientOptions.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<Response|*>} - 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/fetch-missing-url/', 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|| options instanceof String) \n\t\t{\n\t\t\tthrow metroError('metro.client.fetch: Invalid options parameter '+metroURL+'client/fetch-invalid-options/', options)\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.clientOptions?.middlewares?.slice() || [])\n\t\toptions = Object.assign({}, this.clientOptions, 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(deepClone(this.clientOptions), ...options)\n\t}\n\n\tget location() {\n\t\treturn this.clientOptions.url\n\t}\n\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(...deepClone(options))\n}\n\n/*\n//FIXME: is this needed?\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*/\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\t//FIXME: test and see if appendHeaders is needed\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 {<RequestOptions|Request|string|URL|URLSearchParams|FormData|ReadableStream|\n * Blob|ArrayBuffer|DataView|TypedArray>} ...options - request options, handled in order\n * \n * Returns a new metro Request object\n * @param {<RequestOptions|Request|string|URL|URLSearchParams|FormData|ReadableStream|\n * Blob|ArrayBuffer|DataView|TypedArray>} ...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' ? url(window.location) : url('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 r = new Request(requestParams.url, requestParams)\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 globalThis.TypedArray=='undefined' || !(data instanceof globalThis.TypedArray))\n\t\t) {\n\t\t\t// if we are here, body is set with an object of a type\n\t\t\t// not natively understood by Request, coerce it to a string\n\t\t\t// using toString({headers}) instead of just toString()\n\t\t\tif (typeof data.toString == 'function') {\n\t\t\t\trequestParams.body = data.toString({headers:r.headers})\n\t\t\t\tr = new Request(requestParams.url, requestParams)\n\t\t\t}\n\t\t}\n\t}\n\tObject.freeze(r)\n\treturn new Proxy(r, {\n\t\tget(target, prop) {\n\t\t\tlet result\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\tresult = target\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\tresult = true\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\tresult = 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 'data':\n\t\t\t\t\tresult = data\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\t\t\tif (prop === 'clone') {\n\t\t\t\t\t\t\t// TODO: set req.data as the body of the clone\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = target[prop].bind(target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn result\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\t//TODO: check if this should use metro.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 {<ResponseOptions|Response|string|URLSearchParams|FormData|ReadableStream|\n * Blob|ArrayBuffer|DataView|TypedArray>} ...options - respomse options, handled in order\n * \n * Returns a new metro Response object\n * @param {<ResponseOptions|Response|string|URLSearchParams|FormData|ReadableStream|\n * Blob|ArrayBuffer|DataView|TypedArray>} ...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 globalThis.TypedArray != 'undefined' && option instanceof globalThis.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\t// if response status is 'null body status', don't set a body\n\t// that is response.status in [101, 204, 205, 304 ] \n\t// see: https://fetch.spec.whatwg.org/#statuses\n\tif ([101, 204, 205, 304 ].includes(responseParams.status)) {\n\t\tresponseParams.body = null\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) {\n\t\t\tlet result\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\tresult = true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\tresult = target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\tresult = 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\tresult = data\n\t\t\t\tbreak\n\t\t\t\tcase 'ok':\n\t\t\t\t\tresult = (target.status>=200) && (target.status<400)\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (typeof target[prop] == 'function') {\n\t\t\t\t\t\tresult = target[prop].bind(target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\t})\n}\n\nfunction appendSearchParams(url, params)\n{\n\tif (typeof params == 'function') {\n\t\tparams(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 {<URL|URLSearchParams|string|Object|Function>} ...options - url options, handled in order\n * \n * Returns a new metro URL object\n * @param {<URL|URLSearchParams|string|Object|Function>} ...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'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\tswitch(param) {\n\t\t\t\t\tcase 'search':\n\t\t\t\t\t\tif (typeof option.search == 'function') {\n\t\t\t\t\t\t\toption.search(u.search, u)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tu.search = new URLSearchParams(option.search)\n\t\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t\tcase 'searchParams':\n\t\t\t\t\t\tappendSearchParams(u, option.searchParams)\n\t\t\t\t\tbreak\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tif (!validParams.includes(param)) {\n\t\t\t\t\t\t\tthrow metroError('metro.url: unknown url parameter '+metroURL+'url/unknown-param-name/', param)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (typeof option[param] == 'function') {\n\t\t\t\t\t\t\toption[param](u[param], u)\n\t\t\t\t\t\t} else if (\n\t\t\t\t\t\t\ttypeof option[param] == 'string' || option[param] instanceof String \n\t\t\t\t\t\t\t|| typeof option[param] == 'number' || option[param] instanceof Number\n\t\t\t\t\t\t\t|| typeof option[param] == 'boolean' || option[param] instanceof Boolean\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tu[param] = ''+option[param]\n\t\t\t\t\t\t} else if (typeof option[param] == 'object' && option[param].toString) {\n\t\t\t\t\t\t\tu[param] = option[param].toString()\n\t\t\t\t\t\t} else {\n\t\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\t}\n\t\t\t\t\tbreak\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) {\n\t\t\tlet result\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\tresult = true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\tresult = target\n\t\t\t\tbreak\n\t\t\t\tcase 'with':\n\t\t\t\t\tresult = 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\tcase 'filename':\n\t\t\t\t\tresult = target.pathname.split('/').pop()\n\t\t\t\tbreak\n\t\t\t\tcase 'folderpath':\n\t\t\t\t\tresult = target.pathname.substring(0,target.pathname.lastIndexOf('\\\\')+1)\n\t\t\t\tbreak\n\t\t\t\tcase 'authority':\n\t\t\t\t\tresult = target.username ?? ''\n\t\t\t\t\tresult += target.password ? ':'+target.password : ''\n\t\t\t\t\tresult += result ? '@' : ''\n\t\t\t\t\tresult += target.hostname\n\t\t\t\t\tresult += target.port ? ':'+target.port : ''\n\t\t\t\t\tresult += '/'\n\t\t\t\t\tresult = target.protocol + '//' + result\n\t\t\t\tbreak\n\t\t\t\tcase 'origin':\n\t\t\t\t\tresult = target.protocol + '//' + target.hostname\n\t\t\t\t\tresult += target.port ? ':' + target.port : ''\n\t\t\t\t\tresult += '/'\n\t\t\t\tbreak\n\t\t\t\tcase 'fragment':\n\t\t\t\t\tresult = target.hash.substring(1)\n\t\t\t\tbreak\n\t\t\t\tcase 'scheme':\n\t\t\t\t\tif (target.protocol) {\n\t\t\t\t\t\tresult = target.protocol.substring(0, target.protocol.length-1)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = ''\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\t\t\tresult = target[prop].bind(target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn result\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 {<FormData|Object>} ...options - url options, handled in order\n * \n * Returns a new metro FormData object\n * @param {<FormData|Object>} ...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 HTMLFormElement) {\n\t\t\toption = new FormData(option)\n\t\t}\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 '+metroURL+'formdata/unknown-option-value/', option)\n\t\t}\n\t}\n\tObject.freeze(params)\n\treturn new Proxy(params, {\n\t\tget(target, prop) {\n\t\t\tlet result\n\t\t\tswitch(prop) {\n\t\t\t\tcase Symbol.metroProxy:\n\t\t\t\t\tresult = true\n\t\t\t\tbreak\n\t\t\t\tcase Symbol.metroSource:\n\t\t\t\t\tresult = target\n\t\t\t\tbreak\n\t\t\t\t//TODO: add toString() that can check\n\t\t\t\t//headers param: toString({headers:request.headers})\n\t\t\t\t//for the content-type\n\t\t\t\tcase 'with':\n\t\t\t\t\tresult = 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\tdefault:\n\t\t\t\t\tif (target[prop] instanceof Function) {\n\t\t\t\t\t\tresult = target[prop].bind(target)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = target[prop]\n\t\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\treturn result\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\nexport function deepClone(object) {\n\tif (Array.isArray(object)) {\n\t\treturn object.slice().map(deepClone)\n\t}\n\tif (object && typeof object==='object') {\n\t\tif (object.__proto__.constructor==Object || !object.__proto__) { // plain objects\n\t\t\tlet result = Object.assign({}, object)\n\t\t\tObject.keys(result).forEach(key => {\n\t\t\t\tresult[key] = deepClone(object[key])\n\t\t\t})\n\t\t\treturn result\n\t\t} else {\n\t\t\treturn object // don't clone custom classes or functions\n\t\t}\n\t}\n\treturn object\n}", "export default function getdatamw()\n{\n\n\treturn async function getdata(req, next) {\n\t\tlet res = await next(req)\n\t\tif (res.ok && res.data) {\n\t\t\treturn res.data\n\t\t}\n\t\treturn res\n\t}\n\n}", "export default function jsonmw(options)\n{\n options = Object.assign({\n contentType: 'application/json',\n reviver: null,\n replacer: null,\n space: ''\n }, options)\n\n return async function json(req, next) {\n if (!req.headers.get('Accept')) {\n req = req.with({\n headers: {\n 'Accept': options.accept ?? options.contentType\n }\n })\n }\n if (req.method!=='GET' && req.method!=='HEAD') {\n //https://developer.mozilla.org/en-US/docs/Web/API/Request/body\n if (req.data && typeof req.data=='object' && !(req.data instanceof ReadableStream)) {\n const contentType = req.headers.get('Content-Type')\n if (!contentType || isPlainText(contentType)) {\n req = req.with({\n headers: {\n 'Content-Type':options.contentType,\n }\n })\n }\n if (isJSON(req.headers.get('Content-Type'))) {\n req = req.with({\n body: JSON.stringify(req.data, options.replacer, options.space)\n })\n }\n }\n }\n let res = await next(req)\n if (isJSON(res.headers.get('Content-Type'))) {\n let tempRes = res.clone()\n let body = await tempRes.text()\n try {\n let json = JSON.parse(body, options.reviver)\n return res.with({\n body: json\n })\n } catch(e) {\n // ignore parse errors\n }\n }\n return res\n }\n}\n\n/*\n this matches:\n - application/json\n - application/ld+json\n - application/json; charset=utf-8\n - application/ld+json; charset=utf-8\n*/\nconst jsonRE = /^application\\/([a-zA-Z0-9\\-_]+\\+)?json\\b/\nfunction isJSON(contentType)\n{\n return jsonRE.exec(contentType)\n}\n\nfunction isPlainText(contentType)\n{\n return /^text\\/plain\\b/.exec(contentType)\n}", "export default function throwermw(options) {\n\n\treturn async function thrower(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 metro from './metro.mjs'\nimport jsonmw from './mw/json.mjs'\nimport throwermw from './mw/thrower.mjs'\nimport getdatamw from './mw/getdata.mjs'\n\n/**\n * Metro API Client, extends Client\n * @param base ClientOptions|URL|String\n * @param methods {name:function,...} list of API methods to expose\n * This class extends the metro client to allow you to add your own\n * api client methods. Methods are bound to this API object.\n * All default client methods (get/post/put/etc.) still work, unless\n * overridden. If a response object has a data part, that will be \n * returned by the api client methods, instead of the normal response\n * The base API class will throw errors for network responses that\n * are not ok (e.g. status >= 400)\n * It will also return response.data, if that is set, instead of response\n */\nexport class API extends metro.Client\n{\n\tconstructor(base, methods, bind=null)\n\t{\n\t\tif (base instanceof metro.Client) {\n\t\t\tsuper(base.clientOptions, throwermw(), getdatamw())\n\t\t} else {\n\t\t\tsuper(base, throwermw(), getdatamw())\n\t\t}\n\t\tif (!bind) {\n\t\t\tbind = this\n\t\t}\n\t\tfor (const methodName in methods) {\n\t\t\tif (typeof methods[methodName] == 'function') {\n\t\t\t\t// all methods have a this pointing to the (root) API class\n\t\t\t\t// so that you can do this.get()/this.post() or this.section.method()\n\t\t\t\t// inside an API method\n\t\t\t\tthis[methodName] = methods[methodName].bind(bind)\n\t\t\t} else if (methods[methodName] && typeof methods[methodName] == 'object') {\n\t\t\t\t// allows for api.section.method()\n\t\t\t\tthis[methodName] = new this.constructor(base, methods[methodName], bind)\n\t\t\t} else { \n\t\t\t\t// allows you to set string/number values in the client api\n\t\t\t\tthis[methodName] = methods[methodName]\n\t\t\t}\n\t\t}\t\t\n\t}\n}\n\n/**\n * This extends the API class to automatically add\n * the jsonmw middleware. So any request.body that is\n * a normal object is automatically translated to JSON\n * Any response that returns JSON is automatically parsed\n * into response.data.\n * If no Accept header is set, it is added.\n */\nexport class JsonAPI extends API\n{\n\tconstructor(base, methods, bind=null) \n\t{\n\t\tif (base instanceof metro.Client) {\n\t\t\tsuper(base.with(jsonmw()), methods, bind)\n\t\t} else {\n\t\t\tsuper(metro.client(base, jsonmw()), methods, bind)\n\t\t}\n\t}\n}\n\n/**\n * Returns a new Metro API object\n * @param {...ClientOptions|string|URL}\n * @return API\n */\nexport function api(...options)\n{\n\treturn new API(...metro.deepClone(options))\n}\n\nexport function jsonApi(...options)\n{\n\treturn new JsonAPI(...metro.deepClone(options))\n}", "import * as m from './metro.mjs'\nimport { api, jsonApi } from './api.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\tapi,\n\tjsonApi\n})\n\nif (!globalThis.metro) {\n\tglobalThis.metro = metro\n}\n\nexport default metro", "/*\nTODO: add assertExplain global flag, so that if assert() fails, you can call explain() with\n the same pattern and it will return text explanation of why it failed, each assertion function must \n then check assertExplain, and return a text explanation of what fails or succeeds\n top level can then filter to show only the failures\n (so that not(x) can show the succeeds message of x)\n*/\n\n/**\n * assertEnabled (Boolean) used to toggle whether the assert()\n * method should test assertions or not.\n */\nglobalThis.assertEnabled = false\n\n/**\n * Enables assertion testing with assert()\n */\nexport function enable() {\n\tglobalThis.assertEnabled = true\n}\n\n/**\n * Disables assertion testing with assert()\n */\nexport function disable() {\n\tglobalThis.assertEnabled = false\n}\n\n/**\n * This function will check the source for the assertions in test, if\n * assertion checking is enabled globally.\n * If it is, and any assertion fails, it will throw an assertError\n * with a list of problems and other details.\n */\nexport function assert(source, test) {\n\tif (globalThis.assertEnabled) {\n\t\tlet problems = fails(source,test)\n\t\tif (problems) {\n\t\t\tconsole.error('\uD83C\uDD70\uFE0F Assertions failed because of:', problems, 'in this source:', source)\n\t\t\tthrow new Error('Assertions failed', {\n\t\t\t\tcause: { problems, source } \n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n */\nexport function Optional(pattern) {\n\treturn function _Optional(data, root, path) {\n\t\tif (typeof data != 'undefined' && data!=null && typeof pattern != 'undefined' ) {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a pattern, always.\n */\nexport function Required(pattern) {\n\treturn function _Required(data, root, path) {\n\t\tif (data==null || typeof data == 'undefined') {\n\t\t\treturn error('data is required', data, pattern || 'any value', path)\n\t\t} else if (typeof pattern != 'undefined') {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a pattern, only if the value is not null or undefined\n * If null or undefined, it does print a warning to the console.\n */\nexport function Recommended(pattern) {\n\treturn function _Recommended(data, root, path) {\n\t\tif (data==null || typeof data == 'undefined') {\n\t\t\twarn('data does not contain recommended value', data, pattern, path)\n\t\t\treturn false\n\t\t} else {\n\t\t\treturn fails(data, pattern, root, path)\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value against a set of patterns, untill one succeeds\n * Returns an error if none succeed\n */\nexport function oneOf(...patterns) { \n\treturn function _oneOf(data, root, path) {\n\t\tfor(let pattern of patterns) {\n\t\t\tif (!fails(data, pattern, root, path)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\treturn error('data does not match oneOf patterns', data, patterns, path)\n\t}\n}\n\n/**\n * Tests a given array of values against a set of patterns\n * If any value does not match one of the patterns, it will return an error\n * If not given an array to test, it will return an error\n */\nexport function anyOf(...patterns) {\n\treturn function _anyOf(data, root, path) {\n\t\tif (!Array.isArray(data)) {\n\t\t\treturn error('data is not an array',data,'anyOf',path)\n\t\t}\n\t\tfor (let value of data) {\n\t\t\tif (oneOf(...patterns)(value)) {\n\t\t\t\treturn error('data does not match anyOf patterns',value,patterns,path)\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n}\n\nexport function allOf(...patterns) {\n\treturn function _allOf(data, root, path) {\n\t\tlet problems = []\n\t\tfor (let pattern of patterns) {\n\t\t\tproblems = problems.concat(fails(data, pattern, root, path))\n\t\t}\n\t\tproblems = problems.filter(Boolean)\n\t\tif (problems.length) {\n\t\t\treturn error('data does not match all given patterns', data, patterns, path, problems)\n\t\t}\n\t}\n}\n\n/**\n * Tests a given value to see if it is a valid (and absolute) URL, by\n * parsing it with the URL() constructor, and then testing the href\n * value to be equal to the initial value.\n */\nexport function validURL(data, root, path) {\n\ttry {\n\t\tif (data instanceof URL) {\n\t\t\tdata = data.href\n\t\t}\n\t\tlet url = new URL(data)\n\t\tif (url.href!=data) {\n\t\t\tif (!(url.href+'/'==data || url.href==data+'/')) {\n\t\t\t\t// new URL() always adds a / as path\n\t\t\t\treturn error('data is not a valid url',data,'validURL',path)\n\t\t\t}\n\t\t}\n\t} catch(e) {\n\t\treturn error('data is not a valid url',data,'validURL',path)\n\t}\n}\n\n/**\n * Tests a given value to see if it looks like a valid email address, by\n * testing it against a regular expression. So there are no guarantees that\n * it is an actual working email address, just that it looks like one.\n */\nexport function validEmail(data, root, path) {\n\tif (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(data)) {\n\t\treturn error('data is not a valid email',data,'validEmail',path)\n\t}\n}\n\n/**\n * Tests a given value to see if it is an object which is an instance of the given\n * constructor\n */\nexport function instanceOf(constructor) {\n\treturn function _instanceOf(data, root, path) {\n\t\tif (!(data instanceof constructor)) {\n\t\t\treturn error('data is not an instanceof pattern',data,constructor,path)\n\t\t}\n\t}\n}\n\n/**\n * Runs the given test pattern on a value, if the test succeeds, it fails\n * the not() test.\n */\nexport function not(pattern) {\n\treturn function _not(data, root, path) {\n\t\tif (!fails(data, pattern, root, path)) {\n\t\t\treturn error('data matches pattern, when required not to', data, pattern, path)\n\t\t}\n\t}\n}\n\n/**\n * returns an array of problems if the data fails to satisfy \n * the assertions in the given pattern, false otherwise\n * @param {any} data The data to match\n * @param {any} pattern The pattern to match\n * @param {any} root Root object for assertions, set to data by default\n * @return {Array|false} Array with problems if the pattern fails, false otherwise\n */\nexport function fails(data, pattern, root, path='') {\n\tif (!root) {\n\t\troot = data\n\t}\n\tlet problems = []\n\tif (pattern === Boolean) {\n\t\tif (typeof data != 'boolean' && !(data instanceof Boolean)) {\n\t\t\tproblems.push(error('data is not a boolean', data, pattern, path))\n\t\t}\t\t\n\t} else if (pattern === Number) {\n\t\tif (typeof data != 'number' && !(data instanceof Number)) {\n\t\t\tproblems.push(error('data is not a number', data, pattern, path))\n\t\t}\n\t} else if (pattern === String) {\n\t\tif (typeof data != 'string' && !(data instanceof String)) {\n\t\t\tproblems.push(error('data is not a string', data, pattern, path))\n\t\t}\n\t\tif (data == \"\") {\n\t\t\tproblems.push(error('data is an empty string, which is not allowed', data, pattern, path))\n\t\t}\n\t} else if (pattern instanceof RegExp) {\n \tif (Array.isArray(data)) {\n\t\t\tlet index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))\n }\n } else if (typeof data == 'undefined') {\n \tproblems.push(error('data is undefined, should match pattern', data, pattern, path))\n \t} else if (!pattern.test(data)) {\n \tproblems.push(error('data does not match pattern', data, pattern, path))\n }\n } else if (pattern instanceof Function) {\n let problem = pattern(data, root, path)\n if (problem) {\n \tif (Array.isArray(problem)) {\n \t\tproblems = problems.concat(problem)\n \t} else {\n\t \tproblems.push(problem)\n\t }\n }\n } else if (Array.isArray(pattern)) {\n\t\tif (!Array.isArray(data)) {\n\t\t\tproblems.push(error('data is not an array',data,[],path))\n\t\t}\n\t\tfor (let p of pattern) {\n\t\t\tfor (let index of data.keys()) {\n\t\t\t\tlet problem = fails(data[index], p, root, path+'['+index+']')\n\t\t\t\tif (Array.isArray(problem)) {\n\t\t\t\t\tproblems = problems.concat(problem)\n\t\t\t\t} else if (problem) {\n\t\t\t\t\tproblems.push(problem)\n\t\t\t\t}\n\t\t\t}\n \t}\n } else if (pattern && typeof pattern == 'object') {\n if (Array.isArray(data)) {\n let index = data.findIndex((element,index) => fails(element,pattern,root,path+'['+index+']'))\n if (index>-1) {\n \tproblems.push(error('data['+index+'] does not match pattern', data[index], pattern, path+'['+index+']'))\n }\n } else if (!data || typeof data != 'object') {\n \tproblems.push(error('data is not an object, pattern is', data, pattern, path))\n } else {\n \tif (data instanceof URLSearchParams) {\n \t\tdata = Object.fromEntries(data)\n \t}\n \tif (pattern instanceof Function) {\n \t\tlet result = fails(data, pattern, root, path)\n\t if (result) {\n\t \tproblems = problems.concat(result)\n\t }\n \t} else {\n\t\t for (const [patternKey, subpattern] of Object.entries(pattern)) {\n\t\t let result = fails(data[patternKey], subpattern, root, path+'.'+patternKey)\n\t\t if (result) {\n\t\t \tproblems = problems.concat(result)\n\t\t }\n\t\t }\n\t\t }\n\t }\n } else {\n \tif (pattern!=data) {\n \t\tproblems.push(error('data and pattern are not equal', data, pattern, path))\n \t}\n }\n if (problems.length) {\n \treturn problems\n }\n return false\n}\n\n/**\n * Returns an object with message, found and expected properties\n */ \nexport function error(message, found, expected, path, problems) {\n\tlet result = {\n\t\tpath,\n\t\tmessage,\n\t\tfound,\n\t\texpected\n\t}\n\tif (problems) {\n\t\tresult.problems = problems\n\t}\n\treturn result\n}\n\nexport function warn(message, data, pattern, path) {\n\tconsole.warn('\uD83C\uDD70\uFE0F Assert: '+path, message, pattern, data)\n}", "export function tokenStore(site) {\n\tlet localState, localTokens\n\tif (typeof localStorage !== 'undefined') {\n\t\tlocalState = {\n\t\t\tget: () => localStorage.getItem('metro/state:'+site),\n\t\t\tset: (value) => localStorage.setItem('metro/state:'+site, value),\n\t\t\thas: () => localStorage.getItem('metro/state:'+site)!==null,\n\t\t\tdelete: () => localStorage.remoteItem('metro/state:'+site)\n\t\t}\n\t\tlocalTokens = {\n\t\t\tget: (name) => JSON.parse(localStorage.getItem(site+':'+name)),\n\t\t\tset: (name, value) => localStorage.setItem(site+':'+name, JSON.stringify(value)),\n\t\t\thas: (name) => localStorage.getItem(site+':'+name)!==null,\n\t\t\tdelete: (name) => localStorage.removeItem(site+':'+name)\n\t\t}\n\t} else {\n\t\tlet stateMap = new Map()\n\t\tlocalState = {\n\t\t\tget: () => stateMap.get('metro/state:'+site),\n\t\t\tset: (value) => stateMap.set('metro/state:'+site, value),\n\t\t\thas: () => stateMap.has('metro/state:'+site),\n\t\t\tdelete: () => stateMap.delete('metro/state:'+site)\n\t\t}\n\t\tlocalTokens = new Map()\n\t}\n\treturn {\n\t\tstate: localState,\n\t\ttokens: localTokens\n\t}\n}", "import * as metro from '@muze-nl/metro/src/metro.mjs'\nimport { assert, Required, validURL } from '@muze-nl/assert'\nimport {tokenStore} from './tokenstore.mjs'\n\n/**\n * oauth2mw returns a middleware for @muze-nl/metro that\n * implements oauth2 authentication in the metro client.\n * it supports the authorization_code, refresh_token and\n * client_credentials grant_type.\n * Since implicit flow is deemed insecure, it is not supported\n * This library follows the OAuth2.1 RFC - https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11)\n * Referenced as Oauth2.1 RFC from here on\n * by default it will use PKCE and generate a random code_verifier,\n * to skip this, set options.oauth2_configuration.code_verifier to false\n */\nexport default function oauth2mw(options)\n{\n\tconst defaultOptions = {\n\t\tclient: metro.client(),\n\t\tforce_authorization: false,\n\t\tsite: 'default',\n\t\toauth2_configuration: {\n\t\t\tauthorization_endpoint: '/authorize',\n\t\t\ttoken_endpoint: '/token',\n\t\t\tredirect_uri: globalThis.document?.location.href,\n\t\t\tgrant_type: 'authorization_code',\n\t\t\tcode_verifier: generateCodeVerifier(64)\n\t\t},\n\t\tauthorize_callback: async url => {\n\t\t\tif (window.location.href != url.href) {\n\t\t\t\twindow.location.replace(url.href)\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\n\tassert(options, {})\t\n\n\tconst oauth2 = Object.assign({}, defaultOptions.oauth2_configuration, options?.oauth2_configuration)\n\toptions = Object.assign({}, defaultOptions, options)\n\toptions.oauth2_configuration = oauth2\n\n\tconst store = tokenStore(options.site)\n\tif (!options.tokens) {\n\t\toptions.tokens = store.tokens\n\t}\n\tif (!options.state) {\n\t\toptions.state = store.state\n\t}\n\n\tassert(options, {\n\t\toauth2_configuration: {\n\t\t\tclient_id: Required(/.+/),\n\t\t\tgrant_type: 'authorization_code',\n\t\t\tauthorization_endpoint: Required(validURL),\n\t\t\ttoken_endpoint: Required(validURL),\n\t\t\tredirect_uri: Required(validURL)\n\t\t}\n\t})\n\n\t// FIXME: for oidc, we need to send the id_token instead of access token...\n\tfor (let option in oauth2) {\n\t\tswitch(option) {\n\t\t\tcase 'access_token':\n\t\t\tcase 'authorization_code':\n\t\t\tcase 'refresh_token':\n\t\t\t\toptions.tokens.set(option, oauth2[option])\n\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * This is the middleware function. It will intercept a request, and if needed\n\t * go through the OAuth2 authorization flow first.\n\t */\n\treturn async function(req, next) {\n\t\tif (options.force_authorization) {\n\t\t\treturn oauth2authorized(req, next)\n\t\t}\n\t\tlet res\n\t\ttry {\n\t\t\tres = await next(req)\n\t\t\tif (res.ok) {\n\t\t\t\treturn res\n\t\t\t}\n\t\t} catch(err) {\n\t\t\tswitch(res?.status) { \n\t\t\t\tcase 400: // Oauth2.1 RFC 3.2.4\n\t\t\t\tcase 401: // in case of incorrect authentication method\n\t\t\t\t\t//FIXME: check payload of response as well? yes - may be able to recover\n\t\t\t\t\treturn oauth2authorized(req, next)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t\tif (!res.ok) {\n\t\t\tswitch(res.status) { \n\t\t\t\tcase 400: // Oauth2.1 RFC 3.2.4\n\t\t\t\tcase 401: // in case of incorrect authentication method\n\t\t\t\t\t//FIXME: check payload of response as well? yes - may be able to recover\n\t\t\t\t\treturn oauth2authorized(req, next)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\treturn res\n\t}\n\n\t/**\n\t * Implements the OAuth2 authorization flow for a request\n\t */\n\tasync function oauth2authorized(req, next)\n\t{\n\t\tgetTokensFromLocation()\n\t\tconst accessToken = options.tokens.get('access_token')\n\t\tconst refreshToken = options.tokens.get('refresh_token')\n\t\tconst tokenIsExpired = isExpired(accessToken)\n\t\tif (!accessToken || (tokenIsExpired && !refreshToken)) {\n\t\t\ttry {\n\t\t\t\tlet token = await fetchAccessToken()\n\t\t\t\tif (!token) {\n\t\t\t\t\treturn metro.response('false')\n\t\t\t\t}\n\t\t\t} catch(e){\n\t\t\t\t//FIXME: handle some errors here\n\t\t\t\tthrow(e)\n\t\t\t}\n\t\t\treturn oauth2authorized(req, next)\n\t\t} else if (tokenIsExpired && refreshToken) {\n\t\t\ttry {\n\t\t\t\tlet token = await refreshAccessToken()\n\t\t\t\tif (!token) {\n\t\t\t\t\treturn metro.response('false')\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\t//FIXME: handle some errors here\n\t\t\t\tthrow(e)\n\t\t\t}\n\t\t\treturn oauth2authorized(req, next)\n\t\t} else {\n\t\t\treq = metro.request(req, {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: accessToken.type+' '+accessToken.value\n\t\t\t\t}\n\t\t\t})\n\t\t\treturn next(req)\n\t\t}\n\t}\n\n\t/**\n\t * Fetches and stores the authorization_code from a redirected URI\n\t * Then removes the authorization_code from the browser URL\n\t * OAuth2 RFC 4.1.2\n\t */\n\tfunction getTokensFromLocation()\n\t{\n\t\tif (typeof window !== 'undefined' && window?.location) {\n\t\t\tlet url = metro.url(window.location)\n\t\t\tlet code, state, params\n\t\t\tif (url.searchParams.has('code')) {\n\t\t\t\tparams = url.searchParams\n\t\t\t\turl = url.with({ search:'' })\n\t\t\t\thistory.pushState({},'',url.href)\n\t\t\t} else if (url.hash) {\n\t\t\t\tlet query = url.hash.substr(1)\n\t\t\t\tparams = new URLSearchParams('?'+query)\n\t\t\t\turl = url.with({ hash:'' })\n\t\t\t\thistory.pushState({},'',url.href)\n\t\t\t}\n\t\t\tif (params) {\n\t\t\t\tcode = params.get('code')\n\t\t\t\tstate = params.get('state')\n\t\t\t\tlet storedState = options.state.get('metro/state')\n\t\t\t\tif (!state || state!==storedState) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (code) {\n\t\t\t\t\toptions.tokens.set('authorization_code', code)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Fetches the access_token. If the authorization_code hasn't been retrieved yet,\n\t * it will first try to get that, using the options.callbacks.authorize function.\n\t * If a refresh_token is also returned, it will store that in the options.tokens storage.\n\t */\n\tasync function fetchAccessToken()\n\t{\n\t\tif (oauth2.grant_type === 'authorization_code' && !options.tokens.has('authorization_code')) {\n\t\t\tlet authReqURL = await getAuthorizationCodeURL()\n\t\t\tif (!options.authorize_callback || typeof options.authorize_callback !== 'function') {\n\t\t\t\tthrow metro.metroError('oauth2mw: oauth2 with grant_type:authorization_code requires a callback function in client options.authorize_callback')\n\t\t\t}\n\t\t\tlet token = await options.authorize_callback(authReqURL)\n\t\t\tif (token) {\n\t\t\t\toptions.tokens.set('authorization_code', token)\n\t\t\t} else {\n\t\t\t\treturn false\n\t\t\t}\n\t\t}\n\t\tlet tokenReq = getAccessTokenRequest()\n\t\tlet response = await options.client.post(tokenReq) //OAuth2.1 RFC 3.2\n\t\tif (!response.ok) {\n\t\t\tlet msg = await response.text()\n\t\t\tthrow metro.metroError('OAuth2mw: fetch access_token: '+response.status+': '+response.statusText, {cause: tokenReq} )\n\t\t}\n\t\tlet data = await response.json()\n\t\t// OAuth2.1 RFC 3.2.3\n\t\toptions.tokens.set('access_token', {\n\t\t\tvalue: data.access_token,\n\t\t\texpires: getExpires(data.expires_in),\n\t\t\ttype: data.token_type,\n\t\t\tscope: data.scope\n\t\t})\n\t\tif (data.refresh_token) {\n\t\t\tlet token = {\n\t\t\t\tvalue: data.refresh_token\n\t\t\t}\n\t\t\toptions.tokens.set('refresh_token', token)\n\t\t}\n\t\toptions.tokens.delete('authorization_code') // no longer valid\n\t\treturn data\n\t}\n\n\t/**\n\t * Fetches a new access_token using a stored refresh_token\n\t * If a new refresh_token is also returned, it will update the stored refresh_token\n\t * OAuth2.1 RFC 4.3\n\t */\n\tasync function refreshAccessToken()\n\t{\n\t\tlet refreshTokenReq = getAccessTokenRequest('refresh_token')\n\t\tlet response = await options.client.post(refreshTokenReq)\n\t\tif (!response.ok) {\n\t\t\tthrow metro.metroError('OAuth2mw: refresh access_token: '+response.status+': '+response.statusText, {cause: refreshTokenReq} )\n\t\t}\n\t\tlet data = await response.json()\n\t\toptions.tokens.set('access_token', {\n\t\t\tvalue: data.access_token,\n\t\t\texpires: getExpires(data.expires_in),\n\t\t\ttype: data.token_type,\n\t\t\tscope: data.scope\n\t\t})\n\t\tif (data.refresh_token) {\n\t\t\tlet token = {\n\t\t\t\tvalue: data.refresh_token\n\t\t\t}\n\t\t\toptions.tokens.set('refresh_token', token)\n\t\t} else {\n\t\t\treturn false\n\t\t}\n\t\treturn data\n\t}\n\n\t/**\n\t * Returns the URL to use to get a authorization_code\n\t */\n\tasync function getAuthorizationCodeURL()\n\t{\n\t\tif (!oauth2.authorization_endpoint) {\n\t\t\tthrow metro.metroError('oauth2mw: Missing options.oauth2_configuration.authorization_endpoint')\n\t\t}\n\t\tlet url = metro.url(oauth2.authorization_endpoint, {hash: ''}) // OAuth2.1 RFC 3.1\n\t\tassert(oauth2, {\n\t\t\tclient_id: /.+/,\n\t\t\tredirect_uri: /.+/,\n\t\t\tscope: /.*/\n\t\t})\n\t\tlet search = {\n\t\t\tresponse_type: 'code', // implicit flow uses 'token' here, but is not considered safe, so not supported\n\t\t\tclient_id: oauth2.client_id,\n\t\t\tredirect_uri: oauth2.redirect_uri,\n\t\t\tstate: oauth2.state || createState(40) // OAuth2.1 RFC says optional, but its a good idea to always add/check it\n\t\t}\n\t\tif (oauth2.response_type) {\n\t\t\tsearch.response_type = oauth2.response_type\n\t\t}\n\t\tif (oauth2.response_mode) {\n\t\t\tsearch.response_mode = oauth2.response_mode\n\t\t}\n\t\toptions.state.set(search.state)\n\t\tif (oauth2.client_secret) {\n\t\t\tsearch.client_secret = oauth2.client_secret\n\t\t}\n\t\tif (oauth2.code_verifier) { //PKCE\n\t\t\toptions.tokens.set('code_verifier', oauth2.code_verifier)\n\t\t\tsearch.code_challenge = await generateCodeChallenge(oauth2.code_verifier)\n\t\t\tsearch.code_challenge_method = 'S256'\n\t\t}\n\t\tif (oauth2.scope) {\n\t\t\tsearch.scope = oauth2.scope\n\t\t}\n\t\tif (oauth2.prompt) {\n\t\t\tsearch.prompt = oauth2.prompt\n\t\t}\n\t\treturn metro.url(url, { search })\n\t}\n\n\n\t/**\n\t * Returns a token endpoint request with all the correct parameters, given the\n\t * grant_type. This can then be used in a metro.post.\n\t */\n\tfunction getAccessTokenRequest(grant_type=null)\n\t{\n\t\tassert(oauth2, {\n\t\t\tclient_id: /.+/,\n\t\t\tredirect_uri: /.+/\n\t\t})\n\t\tif (!oauth2.token_endpoint) {\n\t\t\tthrow metro.metroError('oauth2mw: Missing options.endpoints.token url')\n\t\t}\n\t\tlet url = metro.url(oauth2.token_endpoint, {hash: ''}) // OAuth2.1 RFC 3.2\n\t\tlet params = {\n\t\t\tgrant_type: grant_type || oauth2.grant_type,\n\t\t\tclient_id: oauth2.client_id\n\t\t}\n\t\tif (oauth2.client_secret) {\n\t\t\tparams.client_secret = oauth2.client_secret\n\t\t}\n\t\tif (oauth2.scope) {\n\t\t\tparams.scope = oauth2.scope\n\t\t}\n\t\tswitch(params.grant_type) {\n\t\t\tcase 'authorization_code':\n\t\t\t\tparams.redirect_uri = oauth2.redirect_uri\n\t\t\t\tparams.code = options.tokens.get('authorization_code')\n\t\t\t\tconst code_verifier = options.tokens.get('code_verifier') //PKCE\n\t\t\t\t// use previously stored code_verifier, not the current random generated one\n\t\t\t\t// previously stored code_verifier is linked to the code_challenge already sent\n\t\t\t\tif (code_verifier) {\n\t\t\t\t\tparams.code_verifier = code_verifier\n\t\t\t\t}\n\t\t\tbreak\n\t\t\tcase 'client_credentials':\n\t\t\t\t// nothing to add\n\t\t\tbreak\n\t\t\tcase 'refresh_token':\n\t\t\t\tconst refreshToken = options.tokens.get('refresh_token')\n\t\t\t\tparams.refresh_token = refreshToken.value\n\t\t\tbreak\n\t\t\tdefault:\n\t\t\t\tthrow new Error('Unknown grant_type: '.oauth2.grant_type)\n\t\t\tbreak\n\t\t}\n\t\treturn metro.request(url, {method: 'POST', body: new URLSearchParams(params) })\n\t}\n\n}\n\n/**\n * Returns true if the access token is expired. False otherwise.\n */\nexport function isExpired(token)\n{\n\tif (!token) {\n\t\treturn true\n\t}\n\tlet expires = new Date(token.expires)\n\tlet now = new Date();\n\treturn now.getTime() > expires.getTime();\n}\n\n/**\n * Returns a new Date based on a duration, which can either be a date\n * or a number of seconds from now.\n */\nexport function getExpires(duration)\n{\n\tif (duration instanceof Date) {\n\t\treturn new Date(duration.getTime()); // return a copy\n\t}\n\tif (typeof duration === 'number') {\n\t\tlet date = new Date();\n\t\tdate.setSeconds(date.getSeconds() + duration);\n\t\treturn date;\n\t}\n\tthrow new TypeError('Unknown expires type '+duration);\n}\n\n\n/**\n * returns a PKCE code_verifier, as a uint8array\n * pass it to base64url_encode() to get a string\n */\nexport function\tgenerateCodeVerifier(size=64)\n{\n\tconst code_verifier = new Uint8Array(size)\n\tglobalThis.crypto.getRandomValues(code_verifier)\n\treturn base64url_encode(code_verifier)\n}\n\n/**\n * Returns a PKCE code_challenge derived from a code_verifier\n * Note that this is an async function, so you can't just call\n * it in the defaultOptions part of oauth2mw, or it will become async as well\n * and that is not supported using metro.client().with() (yet)\n */\nexport async function generateCodeChallenge(code_verifier)\n{\n\tconst encoder = new TextEncoder()\n\tconst data = encoder.encode(code_verifier)\n\tconst challenge = await globalThis.crypto.subtle.digest('SHA-256', data)\n\treturn base64url_encode(challenge)\n}\n\n/**\n * Base64url encoding, which handles UTF-8 input strings correctly.\n */\nexport function base64url_encode(buffer)\n{\n\tconst byteString = Array.from(new Uint8Array(buffer), b => String.fromCharCode(b)).join('')\n return btoa(byteString)\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n}\n\n/**\n * Creates a random state to use in the authorization code URL\n */\nexport function createState(length)\n{\n\tconst validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n\tlet randomState = ''\n\tlet counter = 0\n while (counter < length) {\n randomState += validChars.charAt(Math.floor(Math.random() * validChars.length))\n counter++\n }\n\treturn randomState\n}\n\n/**\n * Returns true if a parameter 'code' is in the document.location searchParams or\n * in the hash, if parsed as searchParams\n */\nexport function isRedirected() {\n\tlet url = new URL(document.location.href)\n\tif (!url.searchParams.has('code')) {\n\t\tif (url.hash) {\n\t\t\tlet query = url.hash.substr(1)\n\t\t\tparams = new URLSearchParams('?'+query)\n\t\t\tif (params.has('code')) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\treturn true\n}\n\n/**\n * Returns true if there is a valid accessToken or refreshToken in the\n * tokens store.\n * @param (tokensStore.tokens|issuer) tokens - if tokens is a string, it \n * \tis assumed to be the oidc issuer, and tokens are fetched using the default\n * tokenStore. If you use a different tokenStore, pass the tokens section of it here\n */\nexport function isAuthorized(tokens) {\n\tif (typeof tokens == 'string') {//issuer\n\t\ttokens = tokenStore(tokens).tokens\n\t}\n\tlet accessToken = tokens.get('access_token')\n\tif (accessToken && !isExpired(accessToken)) {\n\t\treturn true\n\t}\n\tlet refreshToken = tokens.get('refresh_token')\n\tif (refreshToken) { // assumes refresh token is still valid\n\t\treturn true\n\t}\n\treturn false\n}", "export default function keysStore() {\n\treturn new Promise((resolve, reject) => {\n\t\tconst request = globalThis.indexedDB.open('metro', 1)\n\n\t\trequest.onupgradeneeded = () => request.result.createObjectStore('keyPairs', { keyPath: 'domain'})\n\n\t\trequest.onerror = (event) => {\n\t\t\treject(event)\n\t\t}\n\n\t\trequest.onsuccess = (event) => {\n\t\t\tconst db = event.target.result\n\t\t\tresolve({\n\t\t\t\tset: function(value, key) {\n\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\tconst tx = db.transaction('keyPairs', 'readwrite', {durability: 'strict'})\n\t\t\t\t\t\tconst objectStore = tx.objectStore('keyPairs')\n\t\t\t\t\t\ttx.oncomplete = () => {\n\t\t\t\t\t\t\tresolve()\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttx.onerror = reject\n\t\t\t\t\t\tobjectStore.put(value, key)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tget: function(key) {\n\t\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\t\tconst tx = db.transaction('keyPairs', 'readonly')\n\t\t\t\t\t\tconst objectStore = tx.objectStore('keyPairs')\n\t\t\t\t\t\tconst request = objectStore.get(key)\n\t\t\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\t\t\tresolve(request.result)\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequest.onerror = reject\n\t\t\t\t\t\ttx.onerror = reject\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tclear: function() {\n\t\t\t\t\treturn new Promise((resolve,reject) => {\n\t\t\t\t\t\tconst tx = db.transaction('keyPairs', 'readwrite')\n\t\t\t\t\t\tconst objectStore = tx.objectStore('keyPairs')\n\t\t\t\t\t\tconst request = objectStore.clear()\n\t\t\t\t\t\trequest.onsuccess = () => {\n\t\t\t\t\t\t\tresolve()\n\t\t\t\t\t\t}\n\t\t\t\t\t\trequest.onerror = reject\n\t\t\t\t\t\ttx.onerror = reject\t\t\t\t\t\t\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t})\n}", "const encoder = new TextEncoder();\nconst decoder = new TextDecoder();\nfunction buf(input) {\n if (typeof input === 'string') {\n return encoder.encode(input);\n }\n return decoder.decode(input);\n}\nfunction checkRsaKeyAlgorithm(algorithm) {\n if (typeof algorithm.modulusLength !== 'number' || algorithm.modulusLength < 2048) {\n throw new OperationProcessingError(`${algorithm.name} modulusLength must be at least 2048 bits`);\n }\n}\nfunction subtleAlgorithm(key) {\n switch (key.algorithm.name) {\n case 'ECDSA':\n return { name: key.algorithm.name, hash: 'SHA-256' };\n case 'RSA-PSS':\n checkRsaKeyAlgorithm(key.algorithm);\n return {\n name: key.algorithm.name,\n saltLength: 256 >> 3,\n };\n case 'RSASSA-PKCS1-v1_5':\n checkRsaKeyAlgorithm(key.algorithm);\n return { name: key.algorithm.name };\n case 'Ed25519':\n return { name: key.algorithm.name };\n }\n throw new UnsupportedOperationError();\n}\nasync function jwt(header, claimsSet, key) {\n if (key.usages.includes('sign') === false) {\n throw new TypeError('private CryptoKey instances used for signing assertions must include \"sign\" in their \"usages\"');\n }\n const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(claimsSet)))}`;\n const signature = b64u(await crypto.subtle.sign(subtleAlgorithm(key), key, buf(input)));\n return `${input}.${signature}`;\n}\nconst CHUNK_SIZE = 0x8000;\nfunction encodeBase64Url(input) {\n if (input instanceof ArrayBuffer) {\n input = new Uint8Array(input);\n }\n const arr = [];\n for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {\n arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(arr.join('')).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\nfunction b64u(input) {\n return encodeBase64Url(input);\n}\nfunction randomBytes() {\n return b64u(crypto.getRandomValues(new Uint8Array(32)));\n}\nclass UnsupportedOperationError extends Error {\n constructor(message) {\n super(message ?? 'operation not supported');\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nclass OperationProcessingError extends Error {\n constructor(message) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace?.(this, this.constructor);\n }\n}\nfunction psAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'PS256';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name');\n }\n}\nfunction rsAlg(key) {\n switch (key.algorithm.hash.name) {\n case 'SHA-256':\n return 'RS256';\n default:\n throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name');\n }\n}\nfunction esAlg(key) {\n switch (key.algorithm.namedCurve) {\n case 'P-256':\n return 'ES256';\n default:\n throw new UnsupportedOperationError('unsupported EcKeyAlgorithm namedCurve');\n }\n}\nfunction determineJWSAlgorithm(key) {\n switch (key.algorithm.name) {\n case 'RSA-PSS':\n return psAlg(key);\n case 'RSASSA-PKCS1-v1_5':\n return rsAlg(key);\n case 'ECDSA':\n return esAlg(key);\n case 'Ed25519':\n return 'EdDSA';\n default:\n throw new UnsupportedOperationError('unsupported CryptoKey algorithm name');\n }\n}\nfunction isCryptoKey(key) {\n return key instanceof CryptoKey;\n}\nfunction isPrivateKey(key) {\n return isCryptoKey(key) && key.type === 'private';\n}\nfunction isPublicKey(key) {\n return isCryptoKey(key) && key.type === 'public';\n}\nfunction epochTime() {\n return Math.floor(Date.now() / 1000);\n}\nexport default async function DPoP(keypair, htu, htm, nonce, accessToken, additional) {\n const privateKey = keypair?.privateKey;\n const publicKey = keypair?.publicKey;\n if (!isPrivateKey(privateKey)) {\n throw new TypeError('\"keypair.privateKey\" must be a private CryptoKey');\n }\n if (!isPublicKey(publicKey)) {\n throw new TypeError('\"keypair.publicKey\" must be a public CryptoKey');\n }\n if (publicKey.extractable !== true) {\n throw new TypeError('\"keypair.publicKey.extractable\" must be true');\n }\n if (typeof htu !== 'string') {\n throw new TypeError('\"htu\" must be a string');\n }\n if (typeof htm !== 'string') {\n throw new TypeError('\"htm\" must be a string');\n }\n if (nonce !== undefined && typeof nonce !== 'string') {\n throw new TypeError('\"nonce\" must be a string or undefined');\n }\n if (accessToken !== undefined && typeof accessToken !== 'string') {\n throw new TypeError('\"accessToken\" must be a string or undefined');\n }\n if (additional !== undefined &&\n (typeof additional !== 'object' || additional === null || Array.isArray(additional))) {\n throw new TypeError('\"additional\" must be an object');\n }\n return jwt({\n alg: determineJWSAlgorithm(privateKey),\n typ: 'dpop+jwt',\n jwk: await publicJwk(publicKey),\n }, {\n ...additional,\n iat: epochTime(),\n jti: randomBytes(),\n htm,\n nonce,\n htu,\n ath: accessToken ? b64u(await crypto.subtle.digest('SHA-256', buf(accessToken))) : undefined,\n }, privateKey);\n}\nasync function publicJwk(key) {\n const { kty, e, n, x, y, crv } = await crypto.subtle.exportKey('jwk', key);\n return { kty, crv, e, n, x, y };\n}\nexport async function generateKeyPair(alg, options) {\n let algorithm;\n if (typeof alg !== 'string' || alg.length === 0) {\n throw new TypeError('\"alg\" must be a non-empty string');\n }\n switch (alg) {\n case 'PS256':\n algorithm = {\n name: 'RSA-PSS',\n hash: 'SHA-256',\n modulusLength: options?.modulusLength ?? 2048,\n publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n };\n break;\n case 'RS256':\n algorithm = {\n name: 'RSASSA-PKCS1-v1_5',\n hash: 'SHA-256',\n modulusLength: options?.modulusLength ?? 2048,\n publicExponent: new Uint8Array([0x01, 0x00, 0x01]),\n };\n break;\n case 'ES256':\n algorithm = { name: 'ECDSA', namedCurve: 'P-256' };\n break;\n case 'EdDSA':\n algorithm = { name: 'Ed25519' };\n break;\n default:\n throw new UnsupportedOperationError();\n }\n return (crypto.subtle.generateKey(algorithm, options?.extractable ?? false, ['sign', 'verify']));\n}\n", "import metro from '@muze-nl/metro'\nimport DPoP, {generateKeyPair} from 'dpop'\nimport { assert, Required, Optional, validURL } from '@muze-nl/assert'\nimport keysStore from './keysstore.mjs'\n\nexport default function dpopmw(options) {\n\n\tassert(options, {\n\t\tsite: Required(validURL),\n\t\tauthorization_endpoint: Required(validURL),\n\t\ttoken_endpoint: Required(validURL),\n\t\tdpop_signing_alg_values_supported: Optional([]) // this property is unfortunately rarely supported\n\t})\n\n\treturn async (req, next) => {\n\t\tconst keys = await keysStore()\n\t\tlet keyInfo = await keys.get(options.site)\n\t\tif (!keyInfo) {\n \t\t\t// FIXME fetch from dpop_signing_alg_values_supported\n \t\t\t// which is unfortunately not available usually\n \t\t\tlet keyPair = await generateKeyPair('ES256') // note: don't make them extractable! That potentially allows hackers to steal the privateKey\n\t\t\tkeyInfo = { domain: options.site, keyPair }\n\t\t\tawait keys.set(keyInfo)\n\t\t}\n\t\tconst url = metro.url(req.url)\n\n\t\tif (req.url.startsWith(options.authorization_endpoint)) {\n\t\t\tlet params = req.body\n\t\t\tif (params instanceof URLSearchParams || params instanceof FormData) {\n\t\t\t\tparams.set('dpop_jkt', keyInfo.keyPair.publicKey)\n\t\t\t} else {\n\t\t\t\tparams.dpop_jkt = keyInfo.keyPair.publicKey\n\t\t\t}\n\n\t\t} else if (req.url.startsWith(options.token_endpoint)) {\n\t\t\tconst dpopHeader = await DPoP(keyInfo.keyPair, req.url, req.method)\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'DPoP': dpopHeader\n\t\t\t\t}\n\t\t\t})\n\n\t\t} else if (req.headers.has('Authorization')) { //FIXME: not all requests use the dpop bound access token, so check which key to use, or if to add dpop at all\n\t\t\t// note: don't use options.site here, nonce can differ\n\t\t\tconst nonce = localStorage.getItem(url.host+':nonce') || undefined // null is not acceptible for DpOp()\n\t\t\tconst accessToken = req.headers.get('Authorization').split(' ')[1]\n\t\t\tconst dpopHeader = await DPoP(keyInfo.keyPair, req.url, req.method, nonce, accessToken)\n\t\t\treq = req.with({\n\t\t\t\theaders: {\n\t\t\t\t\t'Authorization': 'DPoP '+accessToken,\n\t\t\t\t\t'DPoP': dpopHeader\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tlet response = await next(req)\n\t\tif (response.headers.get('DPoP-Nonce')) {\n\t\t\t// note: don't use options.site here, nonce can differ\n\t\t\tlocalStorage.setItem(url.host+':nonce', response.headers.get('DPoP-Nonce'))\n\t\t}\n\t\treturn response\n\t}\n\t\n}", "import { error } from '@muze-nl/assert'\n\nexport const MustHave = (...options) => \n\t(value, root) => {\n\t\tif (options.filter(o => root.hasOwnKey(o)).length > 0) {\n\t\t\treturn false\n\t\t}\n\t\treturn error('root data must have all of', root, options)\n\t}\n\nexport const MustInclude = (...options) =>\n\t(value) => {\n\t\tif (Array.isArray(value) && options.filter(o => !value.includes(o)).length == 0) {\n\t\t\treturn false\n\t\t} else {\n\t\t\treturn error('data must be an array which includes',value,options)\n\t\t}\n\t}\n\n//TODO: add link to spec\nexport const validJWK = [\n\t'HS256','HS384','HS512','RS256','RS384','RS512','ES256','ES384','ES512'\n]\n\n//TODO: add link to spec\n// FIXME: enter correct values\nexport const validJWA = [\n\t'HS256','HS384','HS512','RS256','RS384','RS512','ES256','ES384','ES512'\n]\n\n//TODO: add link to spec\nexport const validAuthMethods = [\n\t'client_secret_post', 'client_secret_basic','client_secret_jwt','private_key_jwt'\n]\n", "/**\n * This module adheres to OpenID Connect Discovery 1.0 incorporating errata set 2 - december 15, 2023\n * https://openid.net/specs/openid-connect-discovery-1_0.html\n */\nimport metro from '@muze-nl/metro'\nimport jsonmw from '@muze-nl/metro/src/mw/json.mjs'\nimport throwermw from '@muze-nl/metro/src/mw/thrower.mjs'\nimport { validJWA, MustInclude, validAuthMethods } from './oidc.util.mjs'\nimport { assert, fails, Required, Recommended, Optional, oneOf, anyOf, allOf, validURL, instanceOf, not, error } from '@muze-nl/assert'\n\n/**\n * Given options.issuer will get the .well-known/openid-configuration information\n * parse it, assert if follows the specification and return it as a javascript object\n * @param options.issuer Required: URL with the root of the oidc issuer\n * @param options.client Optional: metro client to use in the request\n * @returns object with openid-configuration\n * @throws Error when a network error occurs while fetching openid-configuration\n * @throws assertError when either the options or the openid-configuration fail assertions (and assertion testing is enabled)\n */\nexport default async function oidcDiscovery(options={}) {\n\tassert(options, {\n\t\tclient: Optional(instanceOf(metro.client().constructor)),\n\t\tissuer: Required(validURL)\n\t})\n\n\tconst defaultOptions = {\n\t\tclient: metro.client().with(throwermw()).with(jsonmw()),\n\t\trequireDynamicRegistration: false\n\t}\n\n\toptions = Object.assign({},defaultOptions,options)\n\n\tconst TestSucceeded = false\n\tfunction MustUseHTTPS(url) {\n\t\treturn TestSucceeded // FIXME todo\n\t}\n\n\t// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata\n\t// @TODO: this is a first approximation of the specced requirements, needs to implement\n\t// all MUST/MUST NOT etc. notes in the specification.\n\tconst openid_provider_metadata = {\n\t\tissuer: Required(allOf(options.issuer, MustUseHTTPS)),\n\t\tauthorization_endpoint: Required(validURL),\n\t\ttoken_endpoint: Required(validURL),\n\t\tuserinfo_endpoint: Recommended(validURL), // todo: test for https protocol\n\t\tjwks_uri: Required(validURL),\n\t\tregistration_endpoint: options.requireDynamicRegistration \n\t\t\t? Required(validURL) \n\t\t\t: Recommended(validURL),\n\t\tscopes_supported: Recommended(MustInclude('openid')),\n\t\tresponse_types_supported: options.requireDynamicRegistration\n\t\t\t? Required(MustInclude('code','id_token','id_token token')) \n\t\t\t: Required([]),\n\t\tresponse_modes_supported: Optional([]),\n\t\tgrant_types_supported: options.requireDynamicRegistration\n\t\t\t? Optional(MustInclude('authorization_code')) // implicit is required according to the spec, but not used in web apps\n\t\t\t: Optional([]),\n\t\tacr_values_supported: Optional([]),\n\t\tsubject_types_supported: Required([]),\n\t\tid_token_signing_alg_values_supported: Required(MustInclude('RS256')),\n\t\tid_token_encryption_alg_values_supported: Optional([]),\n\t\tid_token_encryption_enc_values_supported: Optional([]),\n\t\tuserinfo_signing_alg_values_supported: Optional([]),\n\t\tuserinfo_encryption_alg_values_supported: Optional([]),\n\t\tuserinfo_encryption_enc_values_supported: Optional([]),\n\t\trequest_object_signing_alg_values_supported: Optional(MustInclude('RS256')), // not testing for 'none'\n\t\trequest_object_encryption_alg_values_supported: Optional([]),\n\t\trequest_object_encryption_enc_values_supported: Optional([]),\n\t\ttoken_endpoint_auth_methods_supported: Optional(anyOf(...validAuthMethods)),\n\t\ttoken_endpoint_auth_signing_alg_values_supported: Optional(MustInclude('RS256'), not(MustInclude('none'))),\n\t\tdisplay_values_supported: Optional(anyOf('page','popup','touch','wap')),\n\t\tclaim_types_supported: Optional(anyOf('normal','aggregated','distributed')),\n\t\tclaims_supported: Recommended([]),\n\t\tservice_documentation: Optional(validURL),\n\t\tclaims_locales_supported: Optional([]),\n\t\tui_locales_supported: Optional([]),\n\t\tclaims_parameter_supported: Optional(Boolean),\n\t\trequest_parameter_supported: Optional(Boolean),\n\t\trequest_uri_parameter_supported: Optional(Boolean),\n\t\top_policy_uri: Optional(validURL),\n\t\top_tos_uri: Optional(validURL)\t\n\t}\n\n\t// fetch openid configuration from wellknown and return the json\n\tconst configURL = metro.url(options.issuer, '.well-known/openid-configuration')\n\n\tconst response = await options.client.get(\n\t\t// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest\n\t\t// note: this allows path components in the options.issuer url\n\t\tconfigURL\n\t)\n\tconst openid_config = response.data\n\tassert(openid_config, openid_provider_metadata)\n\n\t// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationValidation\n\tassert(openid_config.issuer, options.issuer)\n\treturn openid_config\n}", "/**\n * This module adheres to OpenID Connect Dynamic Client Registration 1.0 \n * incorporating errata set 2 - december 15, 2023\n * https://openid.net/specs/openid-connect-registration-1_0.html\n */\nimport metro from '@muze-nl/metro'\nimport jsonmw from '@muze-nl/metro/src/mw/json.mjs'\nimport throwermw from '@muze-nl/metro/src/mw/thrower.mjs'\nimport { validJWA, validAuthMethods, MustHave } from './oidc.util.mjs'\nimport { assert, Required, Optional, oneOf, anyOf, validURL, validEmail, not, instanceOf } from '@muze-nl/assert'\n\nexport default async function register(options)\n{\n\n // https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata\n\tconst openid_client_metadata = {\n\t\tredirect_uris: Required([validURL]),\n\t\tresponse_types: Optional([]),\n\t\tgrant_types: Optional(anyOf('authorization_code','refresh_token')), //TODO: match response_types with grant_types\n\t\tapplication_type: Optional(oneOf('native','web')),\n\t\tcontacts: Optional([validEmail]),\n\t\tclient_name: Optional(String),\n\t\tlogo_uri: Optional(validURL),\n\t\tclient_uri: Optional(validURL),\n\t\tpolicy_uri: Optional(validURL),\n\t\ttos_uri: Optional(validURL),\n\t\tjwks_uri: Optional(validURL, not(MustHave('jwks'))),\n\t\tjwks: Optional(validURL, not(MustHave('jwks_uri'))),\n\t\tsector_identifier_uri: Optional(validURL),\n\t\tsubject_type: Optional(String),\n\t\tid_token_signed_response_alg: Optional(oneOf(...validJWA)),\n\t\tid_token_encrypted_response_alg: Optional(oneOf(...validJWA)),\n\t\tid_token_encrypted_response_enc: Optional(oneOf(...validJWA), MustHave('id_token_encrypted_response_alg')),\n\t\tuserinfo_signed_response_alg: Optional(oneOf(...validJWA)),\n\t\tuserinfo_encrypted_response_alg: Optional(oneOf(...validJWA)),\n\t\tuserinfo_encrypted_response_enc: Optional(oneOf(...validJWA), MustHave('userinfo_encrypted_response_alg')),\n\t\trequest_object_signing_alg: Optional(oneOf(...validJWA)),\n\t\trequest_object_encryption_alg: Optional(oneOf(...validJWA)),\n\t\trequest_object_encryption_enc: Optional(oneOf(...validJWA)),\n\t\ttoken_endpoint_auth_method: Optional(oneOf(...validAuthMethods)),\n\t\ttoken_endpoint_auth_signing_alg: Optional(oneOf(...validJWA)),\n\t\tdefault_max_age: Optional(Number),\n\t\trequire_auth_time: Optional(Boolean),\n\t\tdefault_acr_values: Optional([String]),\n\t\tinitiate_login_uri: Optional([validURL]),\n\t\trequest_uris: Optional([validURL])\n\t}\n\n\tassert(options, {\n\t\tclient: Optional(instanceOf(metro.client().constructor)),\n\t\tregistration_endpoint: validURL, \n\t\tclient_info: openid_client_metadata\n\t})\n\n\tconst defaultOptions = {\n\t\tclient: metro.client().with(throwermw()).with(jsonmw()),\n\t\tclient_info: {\n\t\t\tredirect_uris: [ globalThis.document?.location.href ]\n\t\t}\n\t}\n\n\toptions = Object.assign({}, defaultOptions, options)\n\tif (!options.client_info) {\n\t\toptions.client_info = {}\n\t} \n\tif (!options.client_info.redirect_uris) {\n\t\toptions.client_info.redirect_uris = [ globalThis.document?.location.href ]\n\t}\n\tlet response = await options.client\n\t\t.post(options.registration_endpoint, {\n\t\t\tbody: options.client_info\n\t\t})\n\tlet info = response.data\n\tif (!info.client_id || !info.client_secret) {\n\t\tthrow metro.metroError('metro.oidc: Error: dynamic registration of client failed, no client_id or client_secret returned', response)\n\t}\n\toptions.client_info = Object.assign(options.client_info, info)\n\treturn options.client_info\n}", "export default function oidcStore(site) {\n\tlet store\n\tif (typeof localStorage !== 'undefined') {\n\t\tstore = {\n\t\t\tget: (name) => JSON.parse(localStorage.getItem('metro/oidc:'+site+':'+name)),\n\t\t\tset: (name, value) => localStorage.setItem('metro/oidc:'+site+':'+name, JSON.stringify(value)),\n\t\t\thas: (name) => localStorage.getItem('metro/oidc:'+site+':'+name)!==null\n\t\t}\n\t} else {\n\t\tlet storeMap = new Map()\n\t\tstore = {\n\t\t\tget: (name) => JSON.parse(storeMap.get('metro/oidc:'+site+':'+name)||null),\n\t\t\tset: (name, value) => storeMap.set('metro/oidc:'+site+':'+name, JSON.stringify(value)),\n\t\t\thas: (name) => storeMap.has('metro/oidc:'+site+':'+name)\n\t\t}\n\t}\n\treturn store\n}", "import * as metro from '@muze-nl/metro/src/metro.mjs'\nimport oauth2mw, * as oauth2 from '@muze-nl/metro-oauth2/src/oauth2.mjs'\nimport dpopmw from '@muze-nl/metro-oauth2/src/oauth2.dpop.mjs'\nimport { assert, Required, Optional, validURL, instanceOf } from '@muze-nl/assert'\nimport discover from './oidc.discovery.mjs'\nimport register from './oidc.register.mjs'\nimport oidcStore from './oidc.store.mjs'\n\nexport default function oidcmw(options={}) {\n\n\tconst defaultOptions = {\n\t\tclient: metro.client(),\n\t\tforce_authorization: false,\n\t\tuse_dpop: true,\n\t\tauthorize_callback: async url => {\n\t\t\tif (window.location.href != url.href) {\n\t\t\t\twindow.location.replace(url.href)\n\t\t\t}\n\t\t\treturn false\n\t\t}\n\t}\n\n\toptions = Object.assign({}, defaultOptions, options)\n\n\tassert(options, {\n\t\tclient: Required(instanceOf(metro.client().constructor)), // required because it is set in defaultOptions\n\t\tclient_info: Required(),\n\t\tissuer: Required(validURL),\n\t\toauth2: Optional({}),\n\t\topenid_configuration: Optional()\n\t})\n\n\tif (!options.store) {\n\t\toptions.store = oidcStore(options.issuer)\n\t}\n\tif (!options.openid_configuration && options.store.has('openid_configuration')) {\n\t\toptions.openid_configuration = options.store.get('openid_configuration')\n\t}\n\tif (!options.client_info?.client_id && options.store.has('client_info')) {\n\t\toptions.client_info = options.store.get('client_info')\n\t}\n\n\treturn async (req, next) => {\n\t\tlet res\n\t\tif (!options.force_authorization) {\n\t\t\ttry {\n\t\t\t\tres = await next(req)\n\t\t\t} catch(err) {\n\t\t\t\tif (res.status!=401 && res.status!=403) {\n\t\t\t\t\tthrow err\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (res.ok || (res.status!=401 && res.status!=403)) {\n\t\t\t\treturn res\n\t\t\t}\n\t\t}\n\t\tif (!options.openid_configuration) {\n\t\t\toptions.openid_configuration = await discover({\n\t\t\t\tissuer: options.issuer\n\t\t\t})\n\t\t\toptions.store.set('openid_configuration', options.openid_configuration)\n\t\t}\n\n\t\tif (!options.client_info?.client_id) {\n\t\t\tif (!options.openid_configuration.registration_endpoint) {\n\t\t\t\tthrow metro.metroError('metro.oidcmw: Error: issuer '+options.issuer+' does not support dynamic client registration, but you haven\\'t specified a client_id')\n\t\t\t}\n\t\t\toptions.client_info = await register({\n\t\t\t\tregistration_endpoint: options.openid_configuration.registration_endpoint,\n\t\t\t\tclient_info: options.client_info\n\t\t\t})\n\t\t\toptions.store.set('client_info', options.client_info)\n\t\t}\n\n\t\t// now initialize an oauth2 client stack, using options.client as default\n\t\t// with forceAuthentication: true\n\t\tconst scope = options.scope || 'openid'\n\n\t\tconst oauth2Options = Object.assign(\n\t\t\t{\n\t\t\t\tsite: options.issuer,\n\t\t\t\tclient: options.client,\n\t\t\t\tforce_authorization: true,\n\t\t\t\tauthorize_callback: options.authorize_callback,\n\t\t\t\toauth2_configuration: {\n\t\t\t\t\tclient_id: options.client_info?.client_id,\n\t\t\t\t\tclient_secret: options.client_info?.client_secret,\n\t\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t\t\tresponse_type: 'code',\n\t\t\t\t\tresponse_mode: 'query',\n\t\t\t\t\tauthorization_endpoint: options.openid_configuration.authorization_endpoint,\n\t\t\t\t\ttoken_endpoint: options.openid_configuration.token_endpoint,\n\t\t\t\t\tscope, //FIXME: should only use scopes supported by server\n\t\t\t\t\tredirect_uri: options.client_info.redirect_uris[0]\n\t\t\t\t}\n\t\t\t}\n\t\t\t//...\n\t\t)\n\t\t\n\t\tconst storeIdToken = async (req, next) => {\n\t\t\tconst res = await next(req)\n\t\t\tconst contentType = res.headers.get('content-type')\n\t\t\tif (contentType?.startsWith('application/json')) {\n\t\t\t\t//FIXME: check that this is actually the token endpoint\n\t\t\t\tlet id_token = res.data?.id_token\n\t\t\t\tif (!id_token) {\n\t\t\t\t\tconst res2 = res.clone() // otherwise res.body can't be read again\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet data = await res2.json()\n\t\t\t\t\t\tif (data && data.id_token) {\n\t\t\t\t\t\t\tid_token = data.id_token\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t// ignore errors\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (id_token) {\n\t\t\t\t\toptions.store.set('id_token', id_token)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res\n\t\t}\n\n\t\tlet oauth2client = options.client.with(options.issuer).with(storeIdToken)\n\n\t\tif (options.use_dpop) {\n\t\t\tconst dpopOptions = {\n\t\t\t\tsite: options.issuer,\n\t\t\t\tauthorization_endpoint: options.openid_configuration.authorization_endpoint,\n\t\t\t\ttoken_endpoint: options.openid_configuration.token_endpoint,\n\t\t\t\tdpop_signing_alg_values_supported: options.openid_configuration.dpop_signing_alg_values_supported\n\t\t\t}\n\t\t\toauth2client = oauth2client.with(dpopmw(dpopOptions)) // add DPoP headers in requests with Authorization headers\n\t\t\toauth2Options.client = oauth2client // make sure oath2 token request use dpop\n\t\t}\n\n\t\toauth2client = oauth2client.with(oauth2mw(oauth2Options))\n\n\t\tres = await oauth2client.fetch(req)\n\n\t\treturn res\n\t}\n\n}\n\nexport function isRedirected() {\n\treturn oauth2.isRedirected()\n}\n\nexport function idToken(options) {\n\tif (!options.store) {\n\t\tif (!options.issuer) {\n\t\t\tthrow metro.metroError('Must supply options.issuer or options.store to get the id_token')\n\t\t}\n\t\toptions.store = oidcStore(options.issuer)\n\t}\n\treturn options.store.get('id_token')\n}\n", "import metro from '@muze-nl/metro'\nimport oauth2 from '@muze-nl/metro-oauth2'\nimport oidcDiscover from './oidc.discovery.mjs'\nimport oidcRegister from './oidc.register.mjs'\nimport oidcmw, {isRedirected, idToken} from './oidcmw.mjs'\n\nconst oidc = {\n\toidcmw,\n\tdiscover: oidcDiscover,\n\tregister: oidcRegister,\n\tisRedirected,\n\tidToken\n}\n\nif (!globalThis.metro.oidc) {\n\tglobalThis.metro.oidc = oidc\n}\n\nexport default oidc", "export default function oldm(options) {\n\treturn new Context(options)\n}\n\nexport const rdfType = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'\n\nexport const prefixes = {\n\trdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',\n\tsolid: 'http://www.w3.org/ns/solid/terms#',\n\tschema: 'http://schema.org/',\n vcard: 'http://www.w3.org/2006/vcard/ns#'\n}\n\nexport class Context {\n\tconstructor(options) {\n\t\tthis.prefixes = {...prefixes, ...options?.prefixes}\n\t\tif (!this.prefixes['xsd']) {\n\t\t\tthis.prefixes['xsd'] = 'http://www.w3.org/2001/XMLSchema#'\n\t\t}\n\t\tthis.parser = options?.parser\n\t\tthis.writer = options?.writer\n\t\tthis.sources = Object.create(null)\n//\t\tthis.subjects = Object.create(null) // or use a proxy here? should contain all subjects from all sources, merged, readonly\n\t\tthis.separator = options?.separator ?? '$'\n\t}\n\n\tparse(input, url, type) {\n\t\tconst {quads, prefixes} = this.parser(input, url, type)\n\t\tif (prefixes) {\n\t\t\tfor (let prefix in prefixes) {\n\t\t\t\tlet prefixURL = prefixes[prefix]\n\t\t\t\tif (prefixURL.match(/^http(s?):\\/\\/$/i)) {\n\t\t\t\t\tprefixURL += url.substring(prefixURL.length)\n\t\t\t\t} else try {\n\t\t\t\t\tprefixURL = new URL(prefixes[prefix], url).href\n\t\t\t\t} catch(err) {\n\t\t\t\t\tconsole.error('Could not parse prefix', prefixes[prefix], err.message)\n\t\t\t\t}\n\n\t\t\t\tif (!this.prefixes[prefix]) {\n\t\t\t\t\tthis.prefixes[prefix] = prefixURL\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.sources[url] = new Graph(quads, url, type, prefixes, this)\n\t\treturn this.sources[url]\n\t}\n\n\tsetType(literal, shortType) {\n\t\tif (!shortType) {\n\t\t\treturn literal\n\t\t}\n\t\tif (typeof literal == 'string') {\n\t\t\tliteral = new String(literal)\n\t\t} else if (typeof result == 'number') {\n\t\t\tliteral = new Number(literal)\n\t\t}\n\t\tif (typeof literal !== 'object') {\n\t\t\tthrow new Error('cannot set type on ',literal,shortType)\n\t\t}\n\t\tliteral.type = shortType\n\t\treturn literal\n\t}\n\n\tgetType(literal) {\n\t\tif (literal && typeof literal == 'object') {\n\t\t\treturn literal.type\n\t\t}\n\t\treturn null\n\t}\n}\n\nexport class Graph {\n\t#blankNodes = Object.create(null)\n\n\tconstructor(quads, url, mimetype, prefixes, context) {\n\t\tthis.mimetype = mimetype\n\t\tthis.url = url\n\t\tthis.prefixes = prefixes\n\t\tthis.context = context\n\t\tthis.subjects = Object.create(null)\n\t\tfor (let quad of quads) {\n\t\t\tlet subject\n\t\t\tif (quad.subject.termType=='BlankNode') {\n\t\t\t\tlet shortPred = this.shortURI(quad.predicate.id,':')\n\t\t\t\tlet shortObj\n\t\t\t\tswitch(shortPred) {\n\t\t\t\t\tcase 'rdf:first':\n\t\t\t\t\t\tsubject = this.addCollection(quad.subject.id)\n\t\t\t\t\t\tshortObj = this.shortURI(quad.object.id, ':')\n\t\t\t\t\t\tif (shortObj!='rdf:nil') {\n\t\t\t\t\t\t\tconst value = this.getValue(quad.object)\n\t\t\t\t\t\t\tif (value) {\n\t\t\t\t\t\t\t\tsubject.push(value)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\tcontinue\n\t\t\t\t\tcase 'rdf:rest':\n\t\t\t\t\t\tthis.#blankNodes[quad.object.id] = this.#blankNodes[quad.subject.id]\n\t\t\t\t\tcontinue\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tsubject = this.addBlankNode(quad.subject.id)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsubject = this.addNamedNode(quad.subject.id)\n\t\t\t}\n\t\t\tsubject.addPredicate(quad.predicate.id, quad.object)\n\t\t}\n\t\tif (this.subjects[url]) {\n\t\t\tthis.primary = this.subjects[url]\n\t\t} else {\n\t\t\tthis.primary = null\n\t\t}\n\t\tObject.defineProperty(this, 'data', {\n\t\t\tget() {\n\t\t\t\treturn Object.values(this.subjects)\n\t\t\t}\n\t\t})\n\t}\n\n\taddNamedNode(uri) {\n\t\t// make sure any relative uri subject ids are fully qualified\n\t\tlet absURI = new URL(uri, this.url).href\n\t\tif (!this.subjects[absURI]) {\n\t\t\tthis.subjects[absURI] = new NamedNode(absURI, this)\n\t\t}\n\t\treturn this.subjects[absURI]\n\t}\n\n\taddBlankNode(id) {\n\t\tif (!this.#blankNodes[id]) {\n\t\t\tthis.#blankNodes[id] = new BlankNode(this)\n\t\t}\n\t\treturn this.#blankNodes[id]\n\t}\n\n\taddCollection(id) {\n\t\tif (!this.#blankNodes[id]) {\n\t\t\tthis.#blankNodes[id] = new Collection(this)\n\t\t}\n\t\treturn this.#blankNodes[id]\n\t}\n\n\twrite() {\n\t\treturn this.context.writer(this)\n\t}\n\n\tget(shortID) {\n\t\treturn this.subjects[this.fullURI(shortID)]\n\t}\n\n\tfullURI(shortURI, separator=null) {\n\t\tif (!separator) {\n\t\t\tseparator = this.context.separator\n\t\t}\n\t\tconst [prefix, path] = shortURI.split(separator)\n\t\tif (path) {\n\t\t\treturn this.prefixes[prefix]+path \n\t\t}\n\t\treturn shortURI\n\t}\n\n\tshortURI(fullURI, separator=null) {\n\t\tif (!separator) {\n\t\t\tseparator = this.context.separator\n\t\t}\n\t\tfor (let prefix in this.context.prefixes) {\n\t\t\tif (fullURI.startsWith(this.context.prefixes[prefix])) {\n\t\t\t\treturn prefix + separator + fullURI.substring(this.context.prefixes[prefix].length)\n\t\t\t}\n\t\t}\n\t\tif (this.url && fullURI.startsWith(this.url)) {\n\t\t\treturn fullURI.substring(this.url.length)\n\t\t}\n\t\treturn fullURI\n\t}\n\n\t/**\n\t * This sets the type of a literal, usually one of the xsd types\n\t */\n\tsetType(literal, type) {\n\t\tconst shortType = this.shortURI(type)\n\t\treturn this.context.setType(literal, shortType)\n\t}\n\n\t/**\n\t * This returns the type of a literal, or null\n\t */\n\tgetType(literal) {\n\t\treturn this.context.getType(literal)\n\t}\n\n\tsetLanguage(literal, language) {\n\t\tif (typeof literal == 'string') {\n\t\t\tliteral = new String(literal)\n\t\t} else if (typeof result == 'number') {\n\t\t\tliteral = new Number(literal)\n\t\t}\n\t\tif (typeof literal !== 'object') {\n\t\t\tthrow new Error('cannot set language on ',literal)\n\t\t}\n\t\tliteral.language = language\n\t\treturn literal\n\t}\n\n\tgetValue(object) {\n\t\tlet result\n\t\tif (object.termType=='Literal') {\n\t\t\tresult = object.value\n\t\t\tlet datatype = object.datatype?.id\n\t\t\tif (datatype) {\n\t\t\t\tresult = this.setType(result, datatype)\n\t\t\t}\n\t\t\tlet language = object.language\n\t\t\tif (language) {\n\t\t\t\tresult = this.setLanguage(result, language)\n\t\t\t}\n\t\t} else if (object.termType=='BlankNode') {\n\t\t\tresult = this.addBlankNode(object.id)\n\t\t} else {\n\t\t\tresult = this.addNamedNode(object.id)\n\t\t}\n\t\treturn result\n\t}\n\n\n}\n\nexport class BlankNode {\n\n\tconstructor(graph) {\n\t\tObject.defineProperty(this, 'graph', {\n\t\t\tvalue: graph,\n\t\t\twritable: false,\n\t\t\tenumerable: false\n\t\t})\n\t}\n\n\taddPredicate(predicate, object) {\n\t\tif (predicate.id) {\n\t\t\tpredicate = predicate.id\n\t\t}\n\t\tif (predicate==rdfType) {\n\t\t\tlet type = this.graph.shortURI(object.id)\n\t\t\tthis.addType(type)\n\t\t} else {\n\t\t\tconst value = this.graph.getValue(object)\n\t\t\tpredicate = this.graph.shortURI(predicate)\n\t\t\tif (!this[predicate]) {\n\t\t\t\tthis[predicate] = value\n\t\t\t} else if (Array.isArray(this[predicate])) {\n\t\t\t\tthis[predicate].push(value)\n\t\t\t} else {\n\t\t\t\tthis[predicate] = [ this[predicate], value]\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Adds a rdfType value, stored in this.a\n\t * Subjects can have more than one type (or class), unlike literals\n\t * The type value can be any URI, xsdTypes are unexpected here\n\t */\n\taddType(type) {\n\t\tif (!this.a) {\n\t\t\tthis.a = type\n\t\t} else {\n\t\t\tif (!Array.isArray(this.a)) {\n\t\t\t\tthis.a = [ this.a ]\n\t\t\t}\n\t\t\tthis.a.push(type)\n\t\t}\n\t}\n}\n\nexport class NamedNode extends BlankNode {\n\tconstructor(id, graph) {\n\t\tsuper(graph)\n\t\tObject.defineProperty(this, 'id', {\n\t\t\tvalue: id,\n\t\t\twritable: false,\n\t\t\tenumerable: true\n\t\t})\n\t}\n}\n\nexport class Collection extends Array {\n\n\tconstructor(id, graph) {\n\t\tsuper()\n\t\tObject.defineProperty(this, 'graph', {\n\t\t\tvalue: graph,\n\t\t\twritable: false,\n\t\t\tenumerable: false\n\t\t})\n\t}\n\n}", "import oldm from '@muze-nl/oldm'\n\nexport default function oldmmw(options)\n{\n\toptions = Object.assign({\n\t\tcontentType: 'text/turtle',\n\t\tprefixes: {\n\t\t 'ldp': 'http://www.w3.org/ns/ldp#',\n\t\t 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',\n\t\t 'dct': 'http://purl.org/dc/terms/',\n\t\t 'stat': 'http://www.w3.org/ns/posix/stat#',\n\t\t 'turtle': 'http://www.w3.org/ns/iana/media-types/text/turtle#',\n\t\t 'schem': 'https://schema.org/',\n\t\t 'solid': 'http://www.w3.org/ns/solid/terms#',\n\t\t 'acl': 'http://www.w3.org/ns/auth/acl#',\n\t\t 'pims': 'http://www.w3.org/ns/pim/space#',\n\t\t 'vcard': 'http://www.w3.org/2006/vcard/ns#',\n\t\t 'foaf': 'http://xmlns.com/foaf/0.1/'\n\t\t},\n\t\tparser: oldm.n3Parser,\n\t\twriter: oldm.n3Writer\n\t}, options)\n\n\tif (!options.prefixes['ldp']) {\n\t\toptions.prefixes['ldp'] = 'http://www.w3.org/ns/ldp#'\n\t}\n\n\tconst context = oldm(options)\n\n\treturn async function oldmmw(req, next) {\n\t\tif (!req.headers.get('Accept')) {\n req = req.with({\n headers: {\n 'Accept': options.accept ?? options.contentType\n }\n })\n }\n if (req.method!=='GET' && req.method!=='HEAD') {\n //https://developer.mozilla.org/en-US/docs/Web/API/Request/body\n if (req.data && typeof req.data=='object' && !(req.data instanceof ReadableStream)) {\n const contentType = req.headers.get('Content-Type')\n if (!contentType || isPlainText(contentType)) {\n req = req.with({\n headers: {\n 'Content-Type': options.contentType,\n }\n })\n }\n if (isLinkedData(req.headers.get('Content-Type'))) {\n req = req.with({\n body: await context.writer(req.data)\n })\n }\n }\n }\n let res = await next(req) \n\t}\n}", "import oldmmw from './oldmmw.mjs'\n\nglobalThis.oldmmw = oldmmw\n\nexport default oldmmw", "/**\n * checks if data is a wrapper object for one of the primitive types\n *\n * @param {mixed} data The data to check\n * @return {Boolean} True if data is a primitive wrapper object\n */\nfunction isPrimitiveWrapper(data)\n{\n return [String, Boolean, Number, BigInt].includes(data?.constructor)\n}\n\nexport function one(selectFn, whichOne='last')\n{\n return (data, key, context) => {\n if (typeof selectFn !== 'function') {\n let selectFnOriginal = selectFn\n selectFn = (o) => {\n return from(o[key]).select(selectFnOriginal);\n }\n }\n let result = selectFn(data, key, context)\n if (Array.isArray(result)) {\n if (whichOne=='last') {\n result = result.pop()\n } else if (whichOne=='first') {\n result = result.shift()\n } else if (typeof whichOne == 'function') {\n result = whichOne(result)\n }\n }\n return result\n }\n}\n\nexport function many(selectFn)\n{\n return (data, key, context) => {\n if (typeof selectFn !== 'function') {\n let selectFnOriginal = selectFn\n selectFn = (o) => {\n return from(o[key]).select(selectFnOriginal);\n }\n }\n let result = selectFn(data, key, context)\n if (result == null) {\n result = []\n } else if (!Array.isArray(result)) {\n result = [result]\n }\n return result\n }\n}\n\nexport function first(...args)\n{\n return (data, key, context) => {\n let result = null\n for (let arg of args) {\n if (typeof arg == 'function') {\n result = arg(data, key, context)\n if (result!=null && result!==undefined && result!==\"\") {\n return result\n }\n } else {\n return arg\n }\n }\n return null\n }\n}\n\n\n\n/**\n * implements a minimal graphql-alike selection syntax, using plain javascript\n * use with from(...arr).select\n *\n * @param {object|function} filter Which keys with which values you want\n * @return Function a function that selects values from objects as defined by filter\n */\nfunction getSelectFn(filter)\n{\n let fns = []\n if (filter instanceof Function) {\n fns.push(filter)\n } else for (const [filterKey, filterValue] of Object.entries(filter)) {\n if (filterValue instanceof Function) {\n fns.push( (data) => {\n const result = {\n [filterKey]: filterValue(data, filterKey, 'select')\n }\n // if (typeof result[filterKey] === 'undefined' && typeof data?.[filterKey] === 'undefined') {\n // return undefined\n // }\n return result\n })\n } else if (!isPrimitiveWrapper(filterValue)) {\n fns.push( (data) => {\n const result = {\n [filterKey]: from(data[filterKey]).select(filterValue)\n }\n // if (typeof result[filterKey] === 'undefined' && typeof data?.[filterKey] === 'undefined') {\n // return undefined\n // }\n return result\n })\n } else {\n fns.push( () => {\n return {\n [filterKey]: filterValue\n }\n })\n }\n }\n if (fns.length==1) {\n return fns[0]\n }\n return (data) => {\n let result = {}\n for (let fn of fns) {\n Object.assign(result, fn(data))\n }\n return result\n }\n}\n\n/**\n * This function checks whether the given data matches the given pattern\n * Pattern can be a function, a regular expression, an object or a literal value\n * The pattern is matched recursively\n * Use with from(...arr).where\n *\n * @param {mixed} pattern The pattern to test\n * @return Function The filter function\n */\nexport function getMatchFn(pattern)\n{\n let fns = []\n if (Array.isArray(pattern)) {\n fns.push(anyOf(...pattern))\n } else if (pattern instanceof RegExp) {\n fns.push((data) => pattern.test(data))\n } else if (pattern instanceof Function) {\n fns.push((data) => pattern(data))\n } else if (!isPrimitiveWrapper(pattern)) {\n let patternMatches = {}\n for (const [wKey, wVal] of Object.entries(pattern)) {\n patternMatches[wKey] = getMatchFn(wVal)\n }\n let matchFn = (data) => {\n if (Array.isArray(data)) {\n return data.filter(element => matchFn(element)).length>0\n }\n if (isPrimitiveWrapper(data)) {\n return false\n }\n for (let wKey in patternMatches) {\n let patternMatchFn = patternMatches[wKey]\n if (!patternMatchFn(data?.[wKey])) {\n return false\n }\n }\n return true\n }\n fns.push(matchFn)\n } else {\n fns.push((data) => {\n if (Array.isArray(data)) {\n return data.filter(element => pattern==element).length>0\n } else {\n return pattern==data\n }\n })\n }\n if (fns.length==1) {\n return fns[0]\n }\n return (data) => {\n for (let fn of fns) {\n if (!fn(data)) {\n return false\n }\n }\n return true\n }\n}\n\n/**\n * If used in a pattern for orderBy(), denotes that the key\n * value should be sorted ascending\n */\nexport const asc = Symbol('asc')\n\n/**\n * If used in a pattern for orderBy(), denotes that the key\n * value should be sorted descending\n */\nexport const desc = Symbol('desc')\n\n/**\n * Returns a function to sort an array according to the pattern. A pattern is\n * an object with keys which are a sub pattern object or\n * one of the asc/desc symbols, or a custom sort(a,b) function\n * @param {mixed} pattern The comparison pattern\n * @return Function The function to use with toSorted()\n */\nexport function getSortFn(pattern)\n{\n let comparisons = Object.entries(pattern)\n let fns = []\n for (let [key,compare] of comparisons) {\n if (compare instanceof Function) {\n fns.push(compare)\n } else if (compare === asc) {\n fns.push((a,b) => (a[key]>b[key] ? 1 : a[key]<b[key] ? -1: 0))\n } else if (compare === desc) {\n fns.push((a,b) => (a[key]<b[key] ? 1 : a[key]>b[key] ? -1: 0))\n } else if (!isPrimitiveWrapper(compare)) {\n let subFn = getSortFn(compare)\n fns.push((a,b) => subFn(a[key],b[key]))\n } else {\n throw new Error('Unknown sort order',compare)\n }\n }\n if (fns.length==1) {\n return fns[0] // special case, if you only have one sort element, just return that, it is faster\n }\n return (a,b) => {\n for (let fn of fns) {\n let result = fn(a,b)\n if (result!==0) {\n return result\n }\n }\n return 0\n }\n}\n\n/**\n * Like getSelectFn this accepts an object, but function values must be\n * reducers.\n * @param {object|function} filter Which keys with which values you want\n * @return Function a function that reduces values\n */\nexport function getAggregateFn(filter)\n{\n let fns = []\n if (filter instanceof Function) {\n fns.push(filter)\n } else for (const [filterKey, filterValue] of Object.entries(filter)) {\n if (filterValue instanceof Function) {\n fns.push( (a, o, i, l) => {\n if (isPrimitiveWrapper(a)) {\n a = {}\n }\n if (o.reduce) {\n a[filterKey] = o.reduce(filterValue, a[filterKey] || [])\n } else {\n a[filterKey] = filterValue(a[filterKey] || [], o, i, l)\n }\n return a\n })\n } else if (!isPrimitiveWrapper(filterValue)) {\n fns.push( (a, o) => {\n if (isPrimitiveWrapper(a)) {\n a = {}\n }\n a[filterKey] = from(o[filterKey]).reduce(filterValue, [])\n return a\n })\n } else {\n fns.push( (a) => {\n if (isPrimitiveWrapper(a)) {\n a = {}\n }\n a[filterKey] = filterValue\n return a\n })\n }\n }\n if (fns.length==1) {\n return fns[0]\n }\n return (a, o, i, l) => {\n let result = {}\n for (let fn of fns) {\n Object.assign(result, fn(a, o, i, l))\n }\n return result\n }\n}\n\n/**\n * This is an alternative implementation of Object.groupBy\n * With support for objects being part of multiple groups\n * So if pointerFn() returns an array, each element of the\n * array is a group\n *\n */\nfunction getMatchingGroups(data, pointerFn)\n{\n let result = {}\n for (let entity of data) {\n let groups = pointerFn(entity)\n if (!Array.isArray(groups)) {\n groups = [groups]\n }\n for (let group of groups) {\n if (typeof group!='string' && !(group instanceof String)) {\n console.warn('JAQT: groupBy(selector) can only handle string values, got:',group)\n continue\n }\n if (!result[group]) {\n result[group] = []\n }\n result[group].push(entity)\n }\n }\n return result\n}\n\n/**\n * Returns a function that groups an array by one or more values defined in the pattern\n *\n * @param (object) data The data to parse and get the group from\n * @param (array) properties The properties to group by, in order, should be pointer functions\n */\nfunction groupBy(data, pointerFunctions)\n{\n let pointerFn = pointerFunctions.shift()\n let groups = getMatchingGroups(data, pointerFn)\n if (pointerFunctions.length) {\n for (let group in groups) {\n groups[group] = groupBy(groups[group], pointerFunctions)\n }\n }\n return groups\n}\n\n/**\n * Creates a function to sum (add) all grouped values, assumes/enforces all values are floats\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.price\n * @return Function function (value, accumulator) => accumulator + value\n */\nexport function sum(fetchFn)\n{\n return (a,o) => {\n if (Array.isArray(a)) {\n a = 0\n }\n a += parseFloat(fetchFn(o)) || 0\n return a\n }\n}\n\n/**\n * Creates a function to average all grouped values, assumes/enforces all values are floats\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.price\n * @return Function function (value, accumulator) => average(accumulator + value)\n */\nexport function avg(fetchFn)\n{\n return (a,o,count) => {\n return +a + ((parseFloat(fetchFn(o)) || 0) - a) / (count+1)\n }\n}\n\n/**\n * Creates a function that removes duplicate values from the grouped data\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.name\n * @return Function\n */\nexport function distinct(fetchFn)\n{\n return (a, o, context) => {\n let v\n if (context=='select') {\n // a is the data param in select() context, o is the key\n v = fetchFn(a)\n if (Array.isArray(v)) { \n return v.filter((val,i,arr) => arr.indexOf(val)===i)\n }\n } else { \n // assume context is reduce, since context is the 3rd param, in reduce that contains the index\n // a is the accumulator, o is the current object/value\n let v = fetchFn(o)\n if (!a.includes[v]) {\n a.push(v)\n }\n }\n return a\n }\n}\n\n/**\n * Creates a function to count all grouped values\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.price\n * @return Function function (value, accumulator) => accumulator + 1\n */\nexport function count()\n{\n return (a) => {\n if (Array.isArray(a)) {\n a = 0\n }\n return a+1\n }\n}\n\n/**\n * Creates a function to find the maximum value in all grouped values, assumes/enforces all values are floats\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.price\n * @return Function function (value, accumulator) => Math.max(accumulator, value)\n */\nexport function max(fetchFn)\n{\n return (a,o) => {\n if (Array.isArray(a)) {\n a = Number.NEGATIVE_INFINITY\n }\n let value = parseFloat(fetchFn(o))\n if (!isNaN(value) && value>a) {\n a = value\n }\n return a\n }\n}\n\n/**\n * Creates a function to find the minimum value in all grouped values, assumes/enforces all values are floats\n *\n * @param fetchFn the function that fetches the correct value, e.g. _.price\n * @return Function function (value, accumulator) => Math.min(accumulator, value)\n */\nexport function min(fetchFn)\n{\n return (a,o) => {\n if (Array.isArray(a)) {\n a = Number.POSITIVE_INFINITY\n }\n let value = parseFloat(fetchFn(o))\n if (!isNaN(value) && value<a) {\n a = value\n }\n return a\n }\n}\n\n\n/**\n * Not inverts the result from the matches function.\n * It returns a function expecting a data parameter and inverts the result\n * of matching that data with the pattern given to not()\n *\n * @param {mixed} pattern The pattern to match not\n * @return {function} A function that inverts the match, with a single data parameter\n */\nexport function not(...pattern)\n{\n let matchFn = getMatchFn(pattern)\n return data => !matchFn(data)\n}\n\n/**\n * AnyOf returns a function that returns true if any of the patterns match the data parameter\n *\n * @param {...mixed} patterns The patterns to test\n * @return {Boolean} True if at least one pattern matches\n */\nexport function anyOf(...patterns)\n{\n let matchFns = patterns.map(pattern => getMatchFn(pattern))\n return data => matchFns.some(fn => fn(data))\n}\n\n/**\n * AllOf returns a function that returns true if all of the patterns match the data parameter\n *\n * @param {...mixed} patterns The patterns to test\n * @return {Boolean} True if all of the patterns match\n */\nexport function allOf(...patterns)\n{\n let matchFns = patterns.map(pattern => getMatchFn(pattern))\n return data => matchFns\n .map(matchFn => matchFn(data))\n .filter(value => !value)\n .length===0\n}\n\n/**\n * Handler for proxying functions like filter, map, etc. So that\n * results of those functions will still be proxied when using from()\n * and you can chain .select() after it\n *\n * @type {Object}\n */\nconst FunctionProxyHandler = {\n apply(target, thisArg, argumentsList)\n {\n let result = target.apply(thisArg,argumentsList)\n if (typeof result === 'object') {\n return new Proxy(result, DataProxyHandler)\n }\n return result\n }\n}\n\n/**\n * Handler for proxying data returned with from()\n *\n * @type {Object}\n */\nconst DataProxyHandler = {\n get(target, property)\n {\n let result = null\n if (typeof property === 'symbol') { // handles iterators and other stuff we don't want to change\n result = target[property]\n }\n if (Array.isArray(target)) {\n switch(property) {\n case 'where':\n result = function(shape) {\n let matchFn = getMatchFn(shape)\n return new Proxy(target\n .filter(element => matchFn(element))\n , DataProxyHandler)\n }\n break\n case 'select':\n result = function(filter) {\n let selectFn = getSelectFn(filter)\n return new Proxy(target\n .map(selectFn)\n , DataProxyHandler)\n }\n break\n case 'reduce':\n result = function(pattern, initial=[]) {\n let aggregateFn = getAggregateFn(pattern)\n let temp = target.reduce(aggregateFn, initial)\n if (Array.isArray(temp)) {\n return new Proxy(temp, DataProxyHandler)\n } else if (!isPrimitiveWrapper(temp)) {\n return new Proxy(temp, GroupByProxyHandler)\n } else {\n return temp\n }\n }\n break\n case 'orderBy':\n result = function(pattern) {\n let sortFn = getSortFn(pattern)\n return new Proxy(target\n .toSorted(sortFn)\n , DataProxyHandler)\n }\n break\n case 'groupBy':\n result = function(...groups) {\n let temp = groupBy(target, groups)\n return new Proxy(temp\n , GroupByProxyHandler)\n }\n break\n }\n }\n if (!result && target && typeof target==='object') {\n if (property==='select') {\n result = function(filter) {\n let selector = getSelectFn(filter)\n return new Proxy(selector(target), DataProxyHandler)\n }\n }\n }\n if (!result && target && typeof target[property]==='function'\n ) {\n result = new Proxy(target[property], FunctionProxyHandler)\n }\n if (!result) {\n result = target[property]\n }\n return result\n }\n}\n\nconst GroupByProxyHandler = {\n get(target, property)\n {\n let result = null\n switch(property) {\n case 'select':\n result = function(filter) {\n let selectFn = getSelectFn(filter)\n let result = {}\n for (let group in target) {\n if (Array.isArray(target[group])) {\n result[group] = new Proxy(target[group].map(selectFn), DataProxyHandler)\n } else {\n result[group] = new Proxy(target[group], GroupByProxyHandler)\n }\n }\n return result\n }\n break\n case 'reduce':\n result = function(pattern, initial=[]) {\n let aggregateFn = getAggregateFn(pattern)\n let result = {}\n for (let group in target) {\n if (Array.isArray(target[group])) {\n let temp = target[group].reduce(aggregateFn, initial)\n if (Array.isArray(temp)) {\n result[group] = new Proxy(temp, DataProxyHandler)\n } else if (!isPrimitiveWrapper(temp)) {\n result[group] = new Proxy(temp, GroupByProxyHandler)\n } else {\n result[group] = temp\n }\n } else {\n result[group] = new Proxy(target[group], GroupByProxyHandler)\n }\n }\n return result\n }\n break\n default:\n if (Array.isArray(target[property])) {\n result = from(target[property])\n } else {\n result = target[property]\n }\n break\n }\n return result\n }\n}\n\n/**\n * Handler for proxying null of undefined values, so that\n * you can still chain the from.where.select functions\n *\n * @type {Object}\n */\nconst EmptyHandler = {\n get(target, property)\n {\n let result = null\n switch(property) {\n case 'where':\n result = function() {\n return new Proxy(new Null(), EmptyHandler)\n }\n break\n case 'reduce':\n case 'select':\n result = function() {\n return null\n }\n break\n case 'orderBy':\n result = function() {\n return new Proxy(new Null(), EmptyHandler)\n }\n break\n case 'groupBy':\n result = function() {\n return new Proxy(new Null(), EmptyHandler)\n }\n break\n }\n if (!result && typeof target?.[property] == 'function') {\n result = target[property];\n }\n return result\n }\n}\n\nclass Null \n{\n toJSON() {\n return null\n }\n}\n\n/**\n * This returns a proxy object for the given data, that adds\n * .where() and .select() functions\n *\n * @param {mixed} data The data to proxy\n * @return {Proxy} The proxy\n */\nexport function from(data)\n{\n if (!data || typeof data !== 'object') {\n return new Proxy(new Null(), EmptyHandler)\n }\n return new Proxy(data, DataProxyHandler)\n}\n\n/**\n * This is the function factory that builds the _ function\n * It will return a function that walks over the root object to\n * return the correct data\n *\n * @param {array} path The list of properties to access in order\n * @return {function} The accessor function that returns the data matching the path\n */\nfunction getPointerFn(path)\n{\n /**\n * The json pointer function\n * @param {mixed} data Any data\n * @param {string} key Optional key for data objects in select context or group in groupBy context\n * @return {mixed} data or data[key]\n */\n return (data, key) => {\n if (path?.length>0) {\n let localPath = path.slice()\n let prop = localPath.shift()\n while(prop) {\n if (Array.isArray(data) && parseInt(prop)!=prop) {\n localPath.unshift(prop) // put it back to call in .map\n return data.map(getPointerFn(localPath))\n } else if (typeof data?.[prop] != 'undefined') {\n data = data[prop]\n } else {\n data = null\n }\n prop = localPath.shift()\n }\n return data\n } else if (key) {\n if (typeof data?.[key] != 'undefined') {\n return data[key]\n } else {\n return null\n }\n } else {\n return data\n }\n }\n}\n\n/**\n * Handler for the getval proxy, used to implement _\n * The get trap handles things like _.key, it returns a function\n * so that select can apply it on result objects\n *\n * @type {Object}\n */\nconst pointerHandler = (path) => {\n if (!path) {\n path = []\n }\n return {\n get(target, property)\n {\n if (property=='constructor' || typeof property == 'symbol') {\n return target[property]\n }\n // creates a new path, which is passed to pointerFn en pointerHandler\n // so it is kept in a new stack frame\n let newpath = path.concat([property])\n return new Proxy(getPointerFn(newpath), pointerHandler(newpath))\n },\n apply(target, thisArg, argumentsList)\n {\n let result = target(...argumentsList)\n if (Array.isArray(result)) {\n result = result.flat(Infinity)\n }\n return result\n }\n }\n}\n\n/**\n * Placeholder in select queries that gets replaced with the\n * object or value being selected, or a specific key of that object\n *\n * @type {Proxy}\n */\nexport const _ = new Proxy(getPointerFn(), pointerHandler())\n", "import Path from '@muze-nl/jsfs/src/Path.js';\nimport HttpAdapter from '@muze-nl/jsfs/src/Adapters/HttpAdapter.js'\nimport {client, url} from '@muze-nl/metro/src/metro.mjs'\nimport getdatamw from '@muze-nl/metro/src/mw/getdata.mjs'\nimport oidc from '@muze-nl/metro-oidc'\nimport oldmmw from '@muze-nl/metro-oldm'\nimport oldm from '@muze-nl/oldm'\nimport { _, from } from '@muze-nl/jaqt/src/jaqt.mjs'\n\nexport default class SolidAdapter extends HttpAdapter {\n \n #client;\n #path;\n\n constructor(metroClient, path='/', solidConfiguration={}) {\n this.#client = client(metroClient)\n .with( oidc.oidcmw(solidConfiguration))\n .with( oldmmw(solidConfiguration))\n this.#path = new Path(path);\n }\n\n get name() {\n return 'SolidAdapter';\n }\n\n\n async list(path) {\n let supportedContentTypes = [\n 'text/turtle'\n ];\n let result = await this.read(path)\n if (result.data) {\n from(result.data)\n .where({\n a: 'ldp$Resource'\n })\n .select({\n filename: o => jsfs.path.filename(metro.url(o.id).pathname),\n path: o => metro.url(o.id).pathname,\n type: o => o.a.includes('ldp$Container') ? 'folder' : 'file'\n })\n } else {\n throw new Error(path+' could not be parsed', {cause: result}) \n }\n }\n\n}", "import SolidAdapter from './SolidAdapter.js'\n\nexport default SolidAdapter\n\nglobalThis.SolidAdapter = SolidAdapter"],
5
+ "mappings": "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",
6
+ "names": ["Path", "_Path", "#value", "path", "cwd", "pathnames", "result", "entry", "reducer", "initial", "callback", "HttpAdapter", "_HttpAdapter", "#baseUrl", "#path", "#exceptionHandler", "#fetchParams", "baseUrl", "path", "exceptionHandler", "fetchParams", "Path", "supportsRequestStreams", "contents", "metadata", "params", "#fetch", "writer", "response", "result", "#getMimetype", "reader", "supportedContentTypes", "html", "url", "#getUrl", "basePath", "parentUrl", "dom", "links", "link", "testURL", "options", "e", "metro_exports", "__export", "Client", "client", "deepClone", "formdata", "metroError", "request", "response", "trace", "url", "metroURL", "_Client", "options", "option", "#addMiddlewares", "param", "verb", "middlewares", "index", "m", "req", "res", "next", "middleware", "tracers", "tracer", "getRequestParams", "current", "params", "prop", "value", "key", "val", "requestParams", "data", "target", "result", "getResponseParams", "responseParams", "r", "appendSearchParams", "validParams", "u", "entry", "metroConsole", "message", "details", "name", "group", "object", "getdatamw", "req", "next", "res", "jsonmw", "options", "req", "next", "contentType", "isPlainText", "isJSON", "res", "body", "json", "jsonRE", "throwermw", "options", "req", "next", "res", "API", "Client", "base", "methods", "bind", "throwermw", "getdatamw", "methodName", "JsonAPI", "jsonmw", "client", "api", "options", "deepClone", "jsonApi", "metro", "metro_exports", "jsonmw", "throwermw", "api", "jsonApi", "everything_default", "assert", "source", "test", "problems", "fails", "Optional", "pattern", "data", "root", "path", "Required", "error", "Recommended", "warn", "oneOf", "patterns", "anyOf", "value", "allOf", "validURL", "url", "validEmail", "instanceOf", "constructor", "not", "index", "element", "problem", "p", "result", "patternKey", "subpattern", "message", "found", "expected", "tokenStore", "site", "localState", "localTokens", "value", "name", "stateMap", "oauth2mw", "options", "defaultOptions", "client", "generateCodeVerifier", "url", "assert", "oauth2", "store", "tokenStore", "Required", "validURL", "option", "req", "next", "oauth2authorized", "res", "err", "getTokensFromLocation", "accessToken", "refreshToken", "tokenIsExpired", "isExpired", "fetchAccessToken", "response", "e", "refreshAccessToken", "request", "code", "state", "params", "query", "storedState", "authReqURL", "getAuthorizationCodeURL", "metroError", "token", "tokenReq", "getAccessTokenRequest", "msg", "data", "getExpires", "refreshTokenReq", "search", "createState", "generateCodeChallenge", "grant_type", "code_verifier", "expires", "duration", "date", "size", "base64url_encode", "challenge", "buffer", "byteString", "b", "length", "validChars", "randomState", "counter", "isRedirected", "keysStore", "resolve", "reject", "request", "event", "db", "value", "key", "tx", "objectStore", "encoder", "decoder", "buf", "input", "checkRsaKeyAlgorithm", "algorithm", "OperationProcessingError", "subtleAlgorithm", "key", "UnsupportedOperationError", "jwt", "header", "claimsSet", "b64u", "signature", "CHUNK_SIZE", "encodeBase64Url", "arr", "i", "randomBytes", "message", "psAlg", "rsAlg", "esAlg", "determineJWSAlgorithm", "isCryptoKey", "isPrivateKey", "isPublicKey", "epochTime", "DPoP", "keypair", "htu", "htm", "nonce", "accessToken", "additional", "privateKey", "publicKey", "publicJwk", "kty", "e", "x", "y", "crv", "generateKeyPair", "alg", "options", "dpopmw", "options", "assert", "Required", "validURL", "Optional", "req", "next", "keys", "keysStore", "keyInfo", "keyPair", "generateKeyPair", "url", "everything_default", "params", "dpopHeader", "DPoP", "nonce", "accessToken", "response", "MustHave", "options", "value", "root", "o", "error", "MustInclude", "validJWA", "validAuthMethods", "oidcDiscovery", "options", "assert", "Optional", "instanceOf", "everything_default", "Required", "validURL", "defaultOptions", "throwermw", "jsonmw", "TestSucceeded", "MustUseHTTPS", "url", "openid_provider_metadata", "allOf", "Recommended", "MustInclude", "anyOf", "validAuthMethods", "not", "configURL", "openid_config", "register", "options", "openid_client_metadata", "Required", "validURL", "Optional", "anyOf", "oneOf", "validEmail", "not", "MustHave", "validJWA", "validAuthMethods", "assert", "instanceOf", "everything_default", "defaultOptions", "throwermw", "jsonmw", "response", "info", "oidcStore", "site", "store", "name", "value", "storeMap", "oidcmw", "options", "defaultOptions", "client", "url", "assert", "Required", "instanceOf", "validURL", "Optional", "oidcStore", "req", "next", "res", "err", "oidcDiscovery", "metroError", "register", "scope", "oauth2Options", "storeIdToken", "id_token", "res2", "data", "oauth2client", "dpopOptions", "dpopmw", "oauth2mw", "isRedirected", "idToken", "oidc", "oidcmw", "oidcDiscovery", "register", "isRedirected", "idToken", "browser_default", "oldm", "options", "Context", "rdfType", "prefixes", "input", "url", "type", "quads", "prefix", "prefixURL", "err", "Graph", "literal", "shortType", "#blankNodes", "mimetype", "context", "quad", "subject", "shortPred", "shortObj", "value", "uri", "absURI", "NamedNode", "id", "BlankNode", "Collection", "shortID", "shortURI", "separator", "path", "fullURI", "language", "object", "result", "datatype", "graph", "predicate", "oldmmw", "options", "oldm", "context", "req", "next", "contentType", "res", "oldmmw", "src_default", "isPrimitiveWrapper", "data", "getSelectFn", "filter", "fns", "filterKey", "filterValue", "data", "isPrimitiveWrapper", "from", "result", "fn", "getMatchFn", "pattern", "anyOf", "element", "patternMatches", "wKey", "wVal", "matchFn", "patternMatchFn", "asc", "desc", "getSortFn", "comparisons", "key", "compare", "a", "b", "subFn", "getAggregateFn", "o", "i", "l", "getMatchingGroups", "pointerFn", "entity", "groups", "group", "groupBy", "pointerFunctions", "anyOf", "patterns", "matchFns", "pattern", "getMatchFn", "data", "fn", "FunctionProxyHandler", "target", "thisArg", "argumentsList", "result", "DataProxyHandler", "property", "shape", "matchFn", "getMatchFn", "element", "filter", "selectFn", "getSelectFn", "pattern", "initial", "aggregateFn", "getAggregateFn", "temp", "isPrimitiveWrapper", "GroupByProxyHandler", "sortFn", "getSortFn", "groups", "groupBy", "selector", "group", "from", "EmptyHandler", "Null", "data", "getPointerFn", "path", "key", "localPath", "prop", "pointerHandler", "newpath", "_", "SolidAdapter", "HttpAdapter", "#client", "#path", "metroClient", "path", "solidConfiguration", "client", "browser_default", "src_default", "Path", "supportedContentTypes", "result", "from", "browser_default", "SolidAdapter"]
7
+ }
@@ -0,0 +1,7 @@
1
+ import js from "@eslint/js";
2
+ import globals from "globals";
3
+ import { defineConfig } from "eslint/config";
4
+
5
+ export default defineConfig([
6
+ { files: ["**/*.{js,mjs,cjs}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } },
7
+ ]);
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@muze-nl/jsfs-solid",
3
+ "version": "0.1.0",
4
+ "author": "auke@muze.nl",
5
+ "source": "src/SolidAdapter.js",
6
+ "main": "dist/browser.js",
7
+ "type": "module",
8
+ "devDependencies": {
9
+ "@eslint/js": "^9.39.2",
10
+ "esbuild": "^0.25.0",
11
+ "eslint": "^9.39.2",
12
+ "globals": "^16.5.0"
13
+ },
14
+ "description": "A filesystem adapter for JSFS that can read/write Solid Storage PODs",
15
+ "scripts": {
16
+ "test": "echo \"Error: no test specified\" && exit 1",
17
+ "build-dev": "esbuild --bundle src/browser.js --outfile=dist/browser.js --sourcemap;",
18
+ "build": "esbuild --bundle src/browser.js --outfile=dist/browser.min.js --minify --sourcemap;"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/muze-nl/jsfs-solid.git"
23
+ },
24
+ "license": "MIT",
25
+ "bugs": {
26
+ "url": "https://github.com/muze-nl/jsfs-solid/issues"
27
+ },
28
+ "homepage": "https://github.com/muze-nl/jsfs-solid#readme",
29
+ "dependencies": {
30
+ "@muze-nl/jaqt": "^0.10.3",
31
+ "@muze-nl/jsfs": "^0.3.0",
32
+ "@muze-nl/metro": "^0.6.15",
33
+ "@muze-nl/metro-oidc": "^0.5.3",
34
+ "@muze-nl/metro-oldm": "^0.1.1",
35
+ "@muze-nl/oldm": "^0.3.5"
36
+ }
37
+ }
@@ -0,0 +1,47 @@
1
+ import Path from '@muze-nl/jsfs/src/Path.js';
2
+ import HttpAdapter from '@muze-nl/jsfs/src/Adapters/HttpAdapter.js'
3
+ import {client, url} from '@muze-nl/metro/src/metro.mjs'
4
+ import getdatamw from '@muze-nl/metro/src/mw/getdata.mjs'
5
+ import oidc from '@muze-nl/metro-oidc'
6
+ import oldmmw from '@muze-nl/metro-oldm'
7
+ import oldm from '@muze-nl/oldm'
8
+ import { _, from } from '@muze-nl/jaqt/src/jaqt.mjs'
9
+
10
+ export default class SolidAdapter extends HttpAdapter {
11
+
12
+ #client;
13
+ #path;
14
+
15
+ constructor(metroClient, path='/', solidConfiguration={}) {
16
+ this.#client = client(metroClient)
17
+ .with( oidc.oidcmw(solidConfiguration))
18
+ .with( oldmmw(solidConfiguration))
19
+ this.#path = new Path(path);
20
+ }
21
+
22
+ get name() {
23
+ return 'SolidAdapter';
24
+ }
25
+
26
+
27
+ async list(path) {
28
+ let supportedContentTypes = [
29
+ 'text/turtle'
30
+ ];
31
+ let result = await this.read(path)
32
+ if (result.data) {
33
+ from(result.data)
34
+ .where({
35
+ a: 'ldp$Resource'
36
+ })
37
+ .select({
38
+ filename: o => jsfs.path.filename(metro.url(o.id).pathname),
39
+ path: o => metro.url(o.id).pathname,
40
+ type: o => o.a.includes('ldp$Container') ? 'folder' : 'file'
41
+ })
42
+ } else {
43
+ throw new Error(path+' could not be parsed', {cause: result})
44
+ }
45
+ }
46
+
47
+ }
package/src/browser.js ADDED
@@ -0,0 +1,5 @@
1
+ import SolidAdapter from './SolidAdapter.js'
2
+
3
+ export default SolidAdapter
4
+
5
+ globalThis.SolidAdapter = SolidAdapter