@optionfactory/ful 0.18.0 → 0.19.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.
@@ -1 +1 @@
1
- {"version":3,"file":"ful.min.mjs","sources":["../src/bindings.mjs","../src/encodings.mjs","../src/forms.mjs","../src/http-client.mjs","../src/storage.mjs","../src/oauth-authorization-code.mjs","../src/timing.mjs","../src/wizard.mjs","../src/app.mjs"],"sourcesContent":["/* global CSS */\n\nfunction extract(extractors, el) {\n const maybeExtractor = extractors[el.dataset['bindExtractor']] || extractors[el.dataset['bindProvide']];\n if (maybeExtractor) {\n return maybeExtractor(el);\n }\n if (el.getAttribute('type') === 'radio') {\n if (!el.checked) {\n return undefined;\n }\n return el.dataset['bindType'] === 'boolean' ? el.value === 'true' : el.value;\n }\n if (el.getAttribute('type') === 'checkbox') {\n return el.checked;\n }\n if (el.dataset['bindType'] === 'boolean') {\n return !el.value ? null : el.value === 'true';\n }\n return el.value || null;\n}\n\nfunction mutate(mutators, el, raw, key, values) {\n const maybeMutator = mutators[el.dataset['bindMutator']] || mutators[el.dataset['bindProvide']];\n if (maybeMutator) {\n maybeMutator(el, raw, key, values);\n return;\n }\n if (el.getAttribute('type') === 'radio') {\n el.checked = el.getAttribute('value') === raw;\n return;\n }\n if (el.getAttribute('type') === 'checkbox') {\n el.checked = raw;\n return;\n }\n el.value = raw;\n}\n\n\nfunction providePath(result, path, value) {\n const keys = path.split(\".\").map((k) => k.match(/^[0-9]+$/) ? +k : k);\n let current = result;\n let previous = null;\n for (let i = 0; ; ++i) {\n const ckey = keys[i];\n const pkey = keys[i - 1];\n if (Number.isInteger(ckey) && !Array.isArray(current)) {\n if (previous !== null) {\n previous[pkey] = current = [];\n } else {\n result = current = [];\n }\n }\n if (i === keys.length - 1) {\n //when value is undefined we only want to define the property if it's not defined \n current[ckey] = value !== undefined ? value : (ckey in current ? current[ckey] : null);\n return result;\n }\n if (current[ckey] === undefined) {\n current[ckey] = {};\n }\n previous = current;\n current = current[ckey];\n }\n}\n\nclass Bindings {\n\n constructor( {extractors, mutators, ignoredChildrenSelector, valueHoldersSelector}) {\n this.extractors = extractors || {};\n this.mutators = mutators || {};\n this.valueHoldersSelector = valueHoldersSelector || 'input[name], select[name], textarea[name]';\n this.ignoredChildrenSelector = ignoredChildrenSelector || '.d-none';\n }\n setValues(el, values) {\n for (let k in values) {\n if (!values.hasOwnProperty(k)) {\n continue;\n }\n Array.from(el.querySelectorAll(`[name='${CSS.escape(k)}']`)).forEach((el) => {\n mutate(this.mutators, el, values[k], k, values);\n });\n }\n }\n getValues(el) {\n return Array.from(el.querySelectorAll(this.valueHoldersSelector))\n .filter((el) => {\n if (el.dataset['bindInclude'] === 'never') {\n return false;\n }\n return el.dataset['bindInclude'] === 'always' || el.closest(this.ignoredChildrenSelector) === null;\n })\n .reduce((result, el) => {\n return providePath(result, el.getAttribute('name'), extract(this.extractors, el));\n }, {});\n }\n}\n\n\n\nexport { Bindings };","\n\nclass Base64 {\n static encode(arrayBuffer, dialect) {\n const d = dialect || Base64.URL_SAFE;\n const len = arrayBuffer.byteLength;\n const view = new Uint8Array(arrayBuffer);\n let res = '';\n for (let i = 0; i < len; i += 3) {\n const v1 = d[view[i] >> 2];\n const v2 = d[((view[i] & 3) << 4) | (view[i + 1] >> 4)];\n const v3 = d[((view[i + 1] & 15) << 2) | (view[i + 2] >> 6)];\n const v4 = d[view[i + 2] & 63];\n res += v1 + v2 + v3 + v4;\n }\n if (len % 3 === 2) {\n res = res.substring(0, res.length - 1);\n } else if (len % 3 === 1) {\n res = res.substring(0, res.length - 2);\n }\n return res;\n }\n static decode(str, dialect) {\n const d = dialect || Base64.URL_SAFE;\n let nbytes = Math.floor(str.length * 0.75);\n for (let i = 0; i !== str.length; ++i) {\n if (str[str.length - i - 1] !== '=') {\n break;\n }\n --nbytes;\n }\n const view = new Uint8Array(nbytes);\n\n let vi = 0;\n let si = 0;\n while (vi < str.length * 0.75) {\n const v1 = d.indexOf(str.charAt(si++));\n const v2 = d.indexOf(str.charAt(si++));\n const v3 = d.indexOf(str.charAt(si++));\n const v4 = d.indexOf(str.charAt(si++));\n view[vi++] = (v1 << 2) | (v2 >> 4);\n view[vi++] = ((v2 & 15) << 4) | (v3 >> 2);\n view[vi++] = ((v3 & 3) << 6) | v4;\n }\n\n return view.buffer;\n }\n}\n\nBase64.STANDARD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nBase64.URL_SAFE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n\nclass Hex {\n static decode(hex) {\n if (hex.length % 2 !== 0) {\n throw new Error(\"invalid length\");\n }\n const lenInBytes = hex.length / 2;\n return new Uint8Array(lenInBytes).map((e, i) => {\n const offset = i * 2;\n const octet = hex.substring(offset, offset + 2);\n return parseInt(octet, 16);\n });\n }\n static encode(bytes, upper) {\n return Array.from(bytes)\n .map(b => b.toString(16))\n .map(b => upper ? b.toUpperCase() : b)\n .map(o => o.padStart(2, 0))\n .join('');\n }\n}\n\nexport { Base64, Hex };","/* global Infinity, CSS */\n\n\nclass Form {\n constructor(el, bindings, {globalErrorsEl, fieldContainerSelector, errorClass, hideClass}) {\n this.el = el;\n this.bindings = bindings;\n this.globalErrorsEl = globalErrorsEl;\n this.fieldContainerSelector = fieldContainerSelector !== undefined ? fieldContainerSelector : Form.DEFAULT_FIELD_CONTAINER_SELECTOR;\n this.errorClass = errorClass || Form.DEFAULT_ERROR_CLASS;\n this.hideClass = hideClass || Form.DEFAULT_HIDE_CLASS;\n }\n setValues(values) {\n return this.bindings.setValues(this.el, values);\n }\n getValues() {\n return this.bindings.getValues(this.el);\n }\n setErrors(errors, scrollFirstErrorIntoView, context) {\n\n this.clearErrors();\n errors\n .map(this.mapError ? this.mapError : (e) => e)\n .filter((e) => e.type === 'FIELD_ERROR' || e.type === 'INVALID_FORMAT')\n .forEach((e) => {\n const name = e.context.replace(\"[\", \".\").replace(\"].\", \".\");\n Array.from(this.el.querySelectorAll(`[name='${CSS.escape(name)}']`))\n .map(el => this.fieldContainerSelector ? el.closest(this.fieldContainerSelector) : el)\n .filter(el => el !== null)\n .forEach(label => {\n label.classList.add(this.errorClass);\n label.dataset['error'] = e.reason;\n });\n });\n if (this.globalErrorsEl) {\n const globalErrors = errors.filter((e) => e.type !== 'FIELD_ERROR' && e.type !== 'INVALID_FORMAT');\n this.globalErrorsEl.innerHTML = globalErrors.map(e => e.reason).join(\"\\n\");\n if (globalErrors.length !== 0) {\n this.globalErrorsEl.classList.remove(this.hideClass);\n }\n }\n if (!scrollFirstErrorIntoView) {\n return;\n }\n const yOffsets = Array.from(this.el.querySelectorAll('.${CSS.escape(this.errorClass)}'))\n .map((label) => label.getBoundingClientRect().y + window.scrollY);\n const firstErrorScrollY = Math.min(...yOffsets);\n if (firstErrorScrollY !== Infinity) {\n window.scroll(window.scrollX, firstErrorScrollY > 100 ? firstErrorScrollY - 100 : 0);\n }\n }\n clearErrors() {\n this.el.querySelectorAll(`.${CSS.escape(this.errorClass)}`).forEach(l => l.classList.remove(this.errorClass));\n if (this.globalErrorsEl) {\n this.globalErrorsEl.innerHTML = '';\n this.globalErrorsEl.classList.add(this.hideClass);\n }\n }\n}\n\nForm.DEFAULT_FIELD_CONTAINER_SELECTOR = 'label';\nForm.DEFAULT_ERROR_CLASS = 'has-error';\nForm.DEFAULT_HIDE_CLASS = 'd-none';\n\n\n/*\n export function forms() {\n }\n \n forms.dropContext = function (context) {\n return function (e) {\n if (e.context && e.context.indexOf(context) === 0) {\n e.context = e.context.substring(context.length);\n }\n return e;\n };\n };\n \n \n Dom.ready(() => {\n document.querySelectorAll('label:not([data-error])').forEach(el => {\n el.dataset['error'] = \"Il valore inserito non è valido\";\n });\n });\n \n Dom.ready(() => {\n Dom.on(document.body, 'change', '[data-pattern]', {}, evt => {\n const el = evt.srcElement;\n const pattern = el.dataset['pattern'];\n const matches = el.value.match(pattern);\n const label = el.closest('label');\n if(label === null){\n return;\n }\n label.classList[matches ? 'remove' : 'add']('has-error'); \n });\n });\n */\nexport { Form };","class ContextInterceptor {\n constructor() {\n const context = document.querySelector(\"meta[name='context']\").getAttribute(\"content\");\n this.context = context.endsWith(\"/\") ? context.substring(0, context.length - 1) : context;\n }\n before(request) {\n const separator = request.resource.startsWith(\"/\") ? \"\" : \"/\";\n request.resource = this.context + separator + request.resource;\n }\n}\n\nclass CsrfTokenInterceptor {\n constructor() {\n this.k = document.querySelector(\"meta[name='_csrf_header']\").getAttribute(\"content\");\n this.v = document.querySelector(\"meta[name='_csrf']\").getAttribute(\"content\");\n }\n before(request) {\n const headers = new Headers(request.options.headers);\n headers.set(this.k, this.v);\n request.options.headers = headers;\n }\n}\n\nclass RedirectOnUnauthorizedInterceptor {\n constructor(redirectUri) {\n this.redirectUri = redirectUri;\n }\n after(request, response) {\n if (response.status !== 401) {\n return;\n }\n window.location.href = redirectUri;\n }\n}\n\nclass Failure extends Error {\n static parseProblems(status, text) {\n const def = [{\n type: \"GENERIC_PROBLEM\",\n context: null,\n reason: `${status}: ${text}`,\n details: null\n }];\n try {\n return text ? JSON.parse(text) : def;\n } catch (e) {\n return def;\n }\n }\n static fromResponse(status, text) {\n return new Failure(status, Failure.parseProblems(status, text));\n }\n constructor(status, problems) {\n super(JSON.stringify(problems));\n this.name = `Failure:${status}`;\n this.status = status;\n this.problems = problems;\n }\n}\n\nclass HttpClientBuilder {\n constructor() {\n this.interceptors = [];\n }\n withContext() {\n this.interceptors.push(new ContextInterceptor());\n return this;\n }\n withCsrfToken() {\n this.interceptors.push(new CsrfTokenInterceptor());\n return this;\n }\n withRedirectOnUnauthorized(redirectUri) {\n this.interceptors.push(new RedirectOnUnauthorizedInterceptor(redirectUri));\n return this;\n }\n withInterceptors(...interceptors) {\n this.interceptors.push(...interceptors);\n return this;\n }\n build() {\n const interceptors = this.interceptors;\n return new HttpClient({interceptors});\n }\n}\n\nclass HttpClient {\n static builder() {\n return new HttpClientBuilder();\n }\n constructor( {interceptors}){\n this.interceptors = interceptors || [];\n }\n async fetch(resource, options) {\n const is = this.interceptors.concat(options.interceptors || []);\n const request = {resource, options};\n await is.forEach(async (i) => {\n if (!i.before) {\n return;\n }\n await i.before(request);\n });\n const response = await fetch(request.resource, request.options);\n await is.forEach(async (i) => {\n if (!i.after) {\n return;\n }\n await i.after(request, response);\n });\n\n return response;\n }\n async json(resource, options) {\n try {\n const response = await this.fetch(resource, options);\n if (!response.ok) {\n const message = await response.text();\n throw Failure.fromResponse(response.status, message);\n }\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } catch (e) {\n if (e instanceof Failure) {\n throw e;\n }\n throw new Failure(0, [{\n type: \"CONNECTION_PROBLEM\",\n context: null,\n reason: e.message,\n details: null\n }]);\n }\n }\n async form(resource, options, uiOptions) {\n const ui = uiOptions || {};\n ui.buttons?.forEach(el => {\n el.setAttribute(\"disabled\", \"disabled\");\n if (ui.loader) {\n el.dataset['oldContent'] = el.innerHTML;\n el.innerHTML = ui.loader;\n }\n });\n try {\n const r = await this.json(resource, options);\n ui.form?.clearErrors();\n return r;\n } catch (e) {\n ui.form?.setErrors(e.problems);\n throw e;\n } finally {\n ui.buttons?.forEach(el => {\n el.removeAttribute(\"disabled\");\n el.innerHTML = el.dataset['oldContent'];\n delete el.dataset['oldContent'];\n });\n }\n }\n}\n\n\n\nexport { HttpClient, Failure };\n","\nclass Storage {\n constructor(prefix, storage) {\n this.prefix = prefix;\n this.storage = storage;\n }\n save(k, v) {\n this.storage.setItem(`${this.prefix}-${k}`, JSON.stringify(v));\n }\n load(k) {\n const got = this.storage.getItem(`${this.prefix}-${k}`);\n return got === undefined ? undefined : JSON.parse(got);\n }\n remove(k) {\n this.storage.removeItem(`${this.prefix}-${k}`);\n }\n pop(k) {\n const decoded = this.load(k);\n this.remove(k);\n return decoded;\n }\n}\n\nclass LocalStorage extends Storage {\n constructor(prefix) {\n super(prefix, localStorage);\n }\n}\n\nclass SessionStorage extends Storage {\n constructor(prefix) {\n super(prefix, sessionStorage);\n }\n}\n\nclass VersionedStorage {\n constructor(storage, key, dataSupplier){\n this.storage = storage;\n this.key = key;\n this.dataSupplier = dataSupplier;\n this.cache = null;\n \n }\n async load(revision){\n const saved = this.storage.load(this.key);\n if (!!saved && saved.revision === revision) {\n this.cache = saved.value;\n return;\n }\n const freshData = await this.dataSupplier(revision, this.key);\n this.storage.save(this.key, {\n revision: revision,\n value: freshData\n });\n this.cache = freshData;\n }\n data(){\n return this.cache;\n }\n}\n\n\n\nexport {LocalStorage, SessionStorage, VersionedStorage};","import { Base64 } from \"./encodings.mjs\";\nimport { SessionStorage } from \"./storage.mjs\";\n\n\nclass AuthorizationCodeFlow {\n static forKeycloak(clientId, realmBaseUrl, redirectUri){\n const authUri = new URL(\"protocol/openid-connect/auth\", realmBaseUrl);\n const tokenUri = new URL(\"protocol/openid-connect/token\", realmBaseUrl);\n const logoutUri = new URL(\"protocol/openid-connect/logout\", realmBaseUrl);\n const scope = \"openid profile\";\n return new AuthorizationCodeFlow(clientId, scope, authUri, tokenUri, logoutUri, redirectUri); \n }\n constructor(clientId, scope, authUri, tokenUri, logoutUri, redirectUri) {\n this.clientId = clientId;\n this.scope = scope;\n this.authUri = authUri;\n this.tokenUri = tokenUri;\n this.logoutUri = logoutUri;\n this.redirectUri = redirectUri;\n this.storage = new SessionStorage(clientId);\n }\n async _auth() {\n const pkceVerifier = Base64.encode(crypto.getRandomValues(new Uint8Array(32)).buffer);\n const pkceChallenge = Base64.encode(await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(pkceVerifier)));\n const state = this.clientId + Base64.encode(crypto.getRandomValues(new Uint8Array(16)).buffer);\n this.storage.save(AuthorizationCodeFlow.PKCE_AND_STATE_KEY, {\n state: state,\n verifier: pkceVerifier\n });\n const url = new URL(this.authUri);\n url.searchParams.set(\"client_id\", this.clientId);\n url.searchParams.set(\"redirect_uri\", this.redirectUri);\n url.searchParams.set(\"response_type\", 'code');\n url.searchParams.set(\"scope\", this.scope);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", pkceChallenge);\n url.searchParams.set(\"code_challenge_method\", 'S256');\n window.location = url;\n }\n async _tokenExchange(code, state) {\n window.history.replaceState('', \"\", this.redirectUri);\n const stateAndVerifier = this.storage.pop(AuthorizationCodeFlow.PKCE_AND_STATE_KEY);\n if (stateAndVerifier.state !== state) {\n throw new Error(\"State mismatch\");\n }\n const response = await fetch(this.tokenUri, {\n method: \"POST\",\n headers: {\n \"Content-Type\": 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams([\n [\"client_id\", this.clientId],\n [\"code\", code],\n [\"grant_type\", \"authorization_code\"],\n [\"code_verifier\", stateAndVerifier.verifier],\n [\"state\", stateAndVerifier.state],\n [\"redirect_uri\", this.redirectUri]\n ])\n });\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\"Error:\" + response.status + \": \" + text);\n }\n const token = await response.json();\n return new AuthorizationCodeFlowSession(this.clientId, token, this.tokenUri, this.logoutUri, this.redirectUri);\n }\n async ensureLoggedIn() {\n const url = new URL(window.location.href);\n const code = url.searchParams.get(\"code\");\n if (code && this.storage.load(AuthorizationCodeFlow.PKCE_AND_STATE_KEY)) {\n //if callback from keycloak and we have our state still stored\n const state = url.searchParams.get(\"state\");\n return await this._tokenExchange(code, state);\n }\n //if not authorized\n await this._auth();\n return null;\n }\n}\nAuthorizationCodeFlow.PKCE_AND_STATE_KEY = \"state-and-verifier\";\n\nclass AuthorizationCodeFlowSession {\n static parseToken(token) {\n const [rawHeader, rawPayload, signature] = token.split(\".\");\n return {\n header: JSON.parse(atob(rawHeader)),\n payload: JSON.parse(atob(rawPayload)),\n signature: signature\n };\n } \n constructor(clientId, token, tokenUri, logoutUri, redirectUri) {\n this.clientId = clientId;\n this.token = token;\n this.tokenUri = tokenUri;\n this.logoutUri = logoutUri;\n this.redirectUri = redirectUri;\n this.accessToken = AuthorizationCodeFlowSession.parseToken(token.access_token);\n this.refreshToken = AuthorizationCodeFlowSession.parseToken(token.refresh_token);\n this.refreshCallback = null;\n }\n onRefresh(callback) {\n this.refreshCallback = callback;\n }\n async refresh() {\n const response = await fetch(this.tokenUri, {\n method: \"POST\",\n headers: {\n \"Content-Type\": 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams([\n [\"client_id\", this.clientId],\n [\"grant_type\", \"refresh_token\"],\n [\"refresh_token\", this.token.refresh_token]\n ])\n });\n if (!response.ok) {\n throw new Error(\"Error:\" + response.code + \": \" + response.text());\n }\n const token = await response.json();\n this.token = token;\n this.accessToken = this._parseToken(token.access_token);\n this.refreshToken = this._parseToken(token.refresh_token);\n if (this.refreshCallback) {\n this.refreshCallback(this.token, this.accessToken, this.refreshToken);\n }\n }\n shouldBeRefreshed(gracePeriod) {\n const now = new Date().getTime();\n const refreshTokenExpiresAt = this.refreshToken.payload.exp * 1000;\n const expired = now > refreshTokenExpiresAt;\n const shouldRefresh = now - gracePeriod > refreshTokenExpiresAt;\n return !expired && shouldRefresh;\n }\n async refreshIf(gracePeriod) {\n if (!this.shouldBeRefreshed(gracePeriod)) {\n return;\n }\n await this.refresh();\n }\n logout() {\n const url = new URL(this.logoutUri);\n url.searchParams.set(\"post_logout_redirect_uri\", this.redirectUri);\n url.searchParams.set(\"id_token_hint\", this.token.id_token);\n window.location = url;\n }\n\n bearerToken() {\n return `Bearer ${this.token.access_token}`;\n }\n \n interceptor(gracePeriodBefore, gracePeriodAfter){\n return new AuthorizationCodeFlowInterceptor(this, gracePeriodBefore, gracePeriodAfter); \n }\n}\n\nclass AuthorizationCodeFlowInterceptor {\n constructor(session, gracePeriodBefore, gracePeriodAfter) {\n this.session = session;\n this.gracePeriodBefore = gracePeriodBefore || 2000;\n this.gracePeriodAfter = gracePeriodAfter || 30000;\n }\n async before(request) {\n await this.session.refreshIf(this.gracePeriodBefore);\n const headers = new Headers(request.options.headers);\n headers.set(\"Authorization\", this.session.bearerToken());\n return request;\n }\n async after(request, response) {\n await this.session.refreshIf(this.gracePeriodAfter);\n return response;\n }\n}\n\n\nexport {AuthorizationCodeFlow, AuthorizationCodeFlowSession, AuthorizationCodeFlowInterceptor };","\nconst timing = {\n sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n },\n DEBOUNCE_DEFAULT: 0,\n DEBOUNCE_IMMEDIATE: 1,\n debounce(timeoutMs, func, options) {\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n let opts = options || timing.DEBOUNCE_DEFAULT;\n\n const later = () => {\n const elapsed = new Date().getTime() - previousTimestamp;\n if (timeoutMs > elapsed) {\n tid = setTimeout(later, timeoutMs - elapsed);\n return;\n }\n tid = null;\n if (opts !== timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n // This check is needed because `func` can recursively invoke `debounced`.\n if (tid === null) {\n args = [];\n }\n };\n\n return function () {\n args = arguments;\n previousTimestamp = new Date().getTime();\n if (tid === null) {\n tid = setTimeout(later, timeoutMs);\n if (opts === timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n }\n };\n },\n THROTTLE_DEFAULT: 0,\n THROTTLE_NO_LEADING: 1,\n THROTTLE_NO_TRAILING: 2,\n throttle(timeoutMs, func, options) {\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n let opts = options || timing.THROTTLE_DEFAULT;\n\n const later = () => {\n previousTimestamp = (opts & timing.THROTTLE_NO_LEADING) ? 0 : new Date().getTime();\n tid = null;\n func(...args);\n if (tid === null) {\n args = [];\n }\n };\n\n return function () {\n const now = new Date().getTime();\n if (!previousTimestamp && (opts & timing.THROTTLE_NO_LEADING)) {\n previousTimestamp = now;\n }\n const remaining = timeoutMs - (now - previousTimestamp);\n args = arguments;\n if (remaining <= 0 || remaining > timeoutMs) {\n if (tid !== null) {\n clearTimeout(tid);\n tid = null;\n }\n previousTimestamp = now;\n func(...args);\n if (tid === null) {\n args = [];\n }\n } else if (tid === null && !(opts & timing.THROTTLE_NO_TRAILING)) {\n tid = setTimeout(later, remaining);\n }\n };\n\n }\n};\n\n\nexport { timing };","class Wizard {\n constructor(el) {\n this.el = el;\n this.progress = [...el.children].filter(e => e.matches(\"header,ol,ul\"));\n\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n if (current === undefined && children.length > 0) {\n children[0].classList.add('active');\n }\n });\n if (this.el.querySelector('section.current') === null) {\n const firstSection = this.el.querySelector('section:first-of-type');\n if (firstSection !== null) {\n firstSection.classList.add('current');\n }\n }\n }\n next() {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n current?.nextElementSibling?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection.classList.remove(\"current\");\n currentSection.nextElementSibling.classList.add('current');\n\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n\n }\n prev() {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n current?.previousElementSibling?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection.classList.remove(\"current\");\n currentSection.previousElementSibling.classList.add('current');\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n }\n moveTo = function (n) {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n p.children[+n]?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection?.classList.remove(\"current\");\n const nthSection = this.el.querySelector(`section:nth-child(${+n})`);\n nthSection.classList.add('current');\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n }\n}\n\n\n\n\nexport { Wizard };\n","class App {\n constructor() {\n this.configurers = [];\n this.initializers = [];\n this.handlers = [];\n this.running = false;\n document.addEventListener(\"DOMContentLoaded\", async () => {\n await Promise.all(this.configurers);\n await Promise.all(this.initializers.map(h => Promise.resolve(h())));\n await Promise.all(this.handlers.map(h => Promise.resolve(h())));\n });\n }\n configure(cb) {\n this.configurers.push(Promise.resolve(cb()));\n return this;\n }\n initialize(cb) {\n this.initializers.push(cb);\n return this;\n }\n ready(cb) {\n this.handlers.push(cb);\n return this;\n }\n}\n\nexport { App };\n"],"names":["mutate","mutators","el","raw","key","values","maybeMutator","dataset","getAttribute","value","checked","Bindings","constructor","extractors","ignoredChildrenSelector","valueHoldersSelector","this","setValues","k","hasOwnProperty","Array","from","querySelectorAll","CSS","escape","forEach","getValues","filter","closest","reduce","result","path","keys","split","map","match","current","previous","i","ckey","pkey","Number","isInteger","isArray","length","undefined","providePath","maybeExtractor","extract","Base64","static","arrayBuffer","dialect","d","URL_SAFE","len","byteLength","view","Uint8Array","res","substring","str","nbytes","Math","floor","vi","si","v1","indexOf","charAt","v2","v3","v4","buffer","STANDARD","Hex","hex","Error","lenInBytes","e","offset","octet","parseInt","bytes","upper","b","toString","toUpperCase","o","padStart","join","Form","bindings","globalErrorsEl","fieldContainerSelector","errorClass","hideClass","DEFAULT_FIELD_CONTAINER_SELECTOR","DEFAULT_ERROR_CLASS","DEFAULT_HIDE_CLASS","setErrors","errors","scrollFirstErrorIntoView","context","clearErrors","mapError","type","name","replace","label","classList","add","reason","globalErrors","innerHTML","remove","yOffsets","getBoundingClientRect","y","window","scrollY","firstErrorScrollY","min","Infinity","scroll","scrollX","l","ContextInterceptor","document","querySelector","endsWith","before","request","separator","resource","startsWith","CsrfTokenInterceptor","v","headers","Headers","options","set","RedirectOnUnauthorizedInterceptor","redirectUri","after","response","status","location","href","Failure","text","def","details","JSON","parse","parseProblems","problems","super","stringify","HttpClientBuilder","interceptors","withContext","push","withCsrfToken","withRedirectOnUnauthorized","withInterceptors","build","HttpClient","async","is","concat","fetch","ok","message","fromResponse","uiOptions","ui","buttons","setAttribute","loader","r","json","form","removeAttribute","Storage","prefix","storage","save","setItem","load","got","getItem","removeItem","pop","decoded","LocalStorage","localStorage","SessionStorage","sessionStorage","VersionedStorage","dataSupplier","cache","revision","saved","freshData","data","AuthorizationCodeFlow","clientId","realmBaseUrl","authUri","URL","tokenUri","logoutUri","scope","pkceVerifier","encode","crypto","getRandomValues","pkceChallenge","subtle","digest","TextEncoder","state","PKCE_AND_STATE_KEY","verifier","url","searchParams","code","history","replaceState","stateAndVerifier","method","body","URLSearchParams","token","AuthorizationCodeFlowSession","get","_tokenExchange","_auth","rawHeader","rawPayload","signature","header","atob","payload","accessToken","parseToken","access_token","refreshToken","refresh_token","refreshCallback","onRefresh","callback","_parseToken","shouldBeRefreshed","gracePeriod","now","Date","getTime","refreshTokenExpiresAt","exp","refresh","logout","id_token","bearerToken","interceptor","gracePeriodBefore","gracePeriodAfter","AuthorizationCodeFlowInterceptor","session","refreshIf","timing","sleep","ms","Promise","resolve","setTimeout","DEBOUNCE_DEFAULT","DEBOUNCE_IMMEDIATE","debounce","timeoutMs","func","tid","args","previousTimestamp","opts","later","elapsed","arguments","THROTTLE_DEFAULT","THROTTLE_NO_LEADING","THROTTLE_NO_TRAILING","throttle","remaining","clearTimeout","Wizard","progress","children","matches","p","firstSection","next","nextElementSibling","currentSection","dispatchEvent","CustomEvent","bubbles","cancelable","prev","previousElementSibling","moveTo","n","App","configurers","initializers","handlers","running","addEventListener","all","h","configure","cb","initialize","ready"],"mappings":"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"}
1
+ {"version":3,"file":"ful.min.mjs","sources":["../src/bindings.mjs","../src/encodings.mjs","../src/forms.mjs","../src/http-client.mjs","../src/storage.mjs","../src/oauth-authorization-code.mjs","../src/timing.mjs","../src/wizard.mjs","../src/app.mjs"],"sourcesContent":["/* global CSS */\n\nfunction extract(extractors, el) {\n const maybeExtractor = extractors[el.dataset['bindExtractor']] || extractors[el.dataset['bindProvide']];\n if (maybeExtractor) {\n return maybeExtractor(el);\n }\n if (el.getAttribute('type') === 'radio') {\n if (!el.checked) {\n return undefined;\n }\n return el.dataset['bindType'] === 'boolean' ? el.value === 'true' : el.value;\n }\n if (el.getAttribute('type') === 'checkbox') {\n return el.checked;\n }\n if (el.dataset['bindType'] === 'boolean') {\n return !el.value ? null : el.value === 'true';\n }\n return el.value || null;\n}\n\nfunction mutate(mutators, el, raw, key, values) {\n const maybeMutator = mutators[el.dataset['bindMutator']] || mutators[el.dataset['bindProvide']];\n if (maybeMutator) {\n maybeMutator(el, raw, key, values);\n return;\n }\n if (el.getAttribute('type') === 'radio') {\n el.checked = el.getAttribute('value') === raw;\n return;\n }\n if (el.getAttribute('type') === 'checkbox') {\n el.checked = raw;\n return;\n }\n el.value = raw;\n}\n\n\nfunction providePath(result, path, value) {\n const keys = path.split(\".\").map((k) => k.match(/^[0-9]+$/) ? +k : k);\n let current = result;\n let previous = null;\n for (let i = 0; ; ++i) {\n const ckey = keys[i];\n const pkey = keys[i - 1];\n if (Number.isInteger(ckey) && !Array.isArray(current)) {\n if (previous !== null) {\n previous[pkey] = current = [];\n } else {\n result = current = [];\n }\n }\n if (i === keys.length - 1) {\n //when value is undefined we only want to define the property if it's not defined \n current[ckey] = value !== undefined ? value : (ckey in current ? current[ckey] : null);\n return result;\n }\n if (current[ckey] === undefined) {\n current[ckey] = {};\n }\n previous = current;\n current = current[ckey];\n }\n}\n\nclass Bindings {\n\n constructor( {extractors, mutators, ignoredChildrenSelector, valueHoldersSelector}) {\n this.extractors = extractors || {};\n this.mutators = mutators || {};\n this.valueHoldersSelector = valueHoldersSelector || 'input[name], select[name], textarea[name]';\n this.ignoredChildrenSelector = ignoredChildrenSelector || '.d-none';\n }\n setValues(el, values) {\n for (let k in values) {\n if (!values.hasOwnProperty(k)) {\n continue;\n }\n Array.from(el.querySelectorAll(`[name='${CSS.escape(k)}']`)).forEach((el) => {\n mutate(this.mutators, el, values[k], k, values);\n });\n }\n }\n getValues(el) {\n return Array.from(el.querySelectorAll(this.valueHoldersSelector))\n .filter((el) => {\n if (el.dataset['bindInclude'] === 'never') {\n return false;\n }\n return el.dataset['bindInclude'] === 'always' || el.closest(this.ignoredChildrenSelector) === null;\n })\n .reduce((result, el) => {\n return providePath(result, el.getAttribute('name'), extract(this.extractors, el));\n }, {});\n }\n}\n\n\n\nexport { Bindings };","\n\nclass Base64 {\n static encode(arrayBuffer, dialect) {\n const d = dialect || Base64.URL_SAFE;\n const len = arrayBuffer.byteLength;\n const view = new Uint8Array(arrayBuffer);\n let res = '';\n for (let i = 0; i < len; i += 3) {\n const v1 = d[view[i] >> 2];\n const v2 = d[((view[i] & 3) << 4) | (view[i + 1] >> 4)];\n const v3 = d[((view[i + 1] & 15) << 2) | (view[i + 2] >> 6)];\n const v4 = d[view[i + 2] & 63];\n res += v1 + v2 + v3 + v4;\n }\n if (len % 3 === 2) {\n res = res.substring(0, res.length - 1);\n } else if (len % 3 === 1) {\n res = res.substring(0, res.length - 2);\n }\n return res;\n }\n static decode(str, dialect) {\n const d = dialect || Base64.URL_SAFE;\n let nbytes = Math.floor(str.length * 0.75);\n for (let i = 0; i !== str.length; ++i) {\n if (str[str.length - i - 1] !== '=') {\n break;\n }\n --nbytes;\n }\n const view = new Uint8Array(nbytes);\n\n let vi = 0;\n let si = 0;\n while (vi < str.length * 0.75) {\n const v1 = d.indexOf(str.charAt(si++));\n const v2 = d.indexOf(str.charAt(si++));\n const v3 = d.indexOf(str.charAt(si++));\n const v4 = d.indexOf(str.charAt(si++));\n view[vi++] = (v1 << 2) | (v2 >> 4);\n view[vi++] = ((v2 & 15) << 4) | (v3 >> 2);\n view[vi++] = ((v3 & 3) << 6) | v4;\n }\n\n return view.buffer;\n }\n}\n\nBase64.STANDARD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nBase64.URL_SAFE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n\nclass Hex {\n static decode(hex) {\n if (hex.length % 2 !== 0) {\n throw new Error(\"invalid length\");\n }\n const lenInBytes = hex.length / 2;\n return new Uint8Array(lenInBytes).map((e, i) => {\n const offset = i * 2;\n const octet = hex.substring(offset, offset + 2);\n return parseInt(octet, 16);\n });\n }\n static encode(bytes, upper) {\n return Array.from(bytes)\n .map(b => b.toString(16))\n .map(b => upper ? b.toUpperCase() : b)\n .map(o => o.padStart(2, 0))\n .join('');\n }\n}\n\nexport { Base64, Hex };","/* global Infinity, CSS */\n\n\nclass Form {\n constructor(el, bindings, {globalErrorsEl, fieldContainerSelector, errorClass, hideClass}) {\n this.el = el;\n this.bindings = bindings;\n this.globalErrorsEl = globalErrorsEl;\n this.fieldContainerSelector = fieldContainerSelector !== undefined ? fieldContainerSelector : Form.DEFAULT_FIELD_CONTAINER_SELECTOR;\n this.errorClass = errorClass || Form.DEFAULT_ERROR_CLASS;\n this.hideClass = hideClass || Form.DEFAULT_HIDE_CLASS;\n }\n setValues(values) {\n return this.bindings.setValues(this.el, values);\n }\n getValues() {\n return this.bindings.getValues(this.el);\n }\n setErrors(errors, scrollFirstErrorIntoView, context) {\n\n this.clearErrors();\n errors\n .map(this.mapError ? this.mapError : (e) => e)\n .filter((e) => e.type === 'FIELD_ERROR' || e.type === 'INVALID_FORMAT')\n .forEach((e) => {\n const name = e.context.replace(\"[\", \".\").replace(\"].\", \".\");\n Array.from(this.el.querySelectorAll(`[name='${CSS.escape(name)}']`))\n .map(el => this.fieldContainerSelector ? el.closest(this.fieldContainerSelector) : el)\n .filter(el => el !== null)\n .forEach(label => {\n label.classList.add(this.errorClass);\n label.dataset['error'] = e.reason;\n });\n });\n if (this.globalErrorsEl) {\n const globalErrors = errors.filter((e) => e.type !== 'FIELD_ERROR' && e.type !== 'INVALID_FORMAT');\n this.globalErrorsEl.innerHTML = globalErrors.map(e => e.reason).join(\"\\n\");\n if (globalErrors.length !== 0) {\n this.globalErrorsEl.classList.remove(this.hideClass);\n }\n }\n if (!scrollFirstErrorIntoView) {\n return;\n }\n const yOffsets = Array.from(this.el.querySelectorAll('.${CSS.escape(this.errorClass)}'))\n .map((label) => label.getBoundingClientRect().y + window.scrollY);\n const firstErrorScrollY = Math.min(...yOffsets);\n if (firstErrorScrollY !== Infinity) {\n window.scroll(window.scrollX, firstErrorScrollY > 100 ? firstErrorScrollY - 100 : 0);\n }\n }\n clearErrors() {\n this.el.querySelectorAll(`.${CSS.escape(this.errorClass)}`).forEach(l => l.classList.remove(this.errorClass));\n if (this.globalErrorsEl) {\n this.globalErrorsEl.innerHTML = '';\n this.globalErrorsEl.classList.add(this.hideClass);\n }\n }\n}\n\nForm.DEFAULT_FIELD_CONTAINER_SELECTOR = 'label';\nForm.DEFAULT_ERROR_CLASS = 'has-error';\nForm.DEFAULT_HIDE_CLASS = 'd-none';\n\n\n/*\n export function forms() {\n }\n \n forms.dropContext = function (context) {\n return function (e) {\n if (e.context && e.context.indexOf(context) === 0) {\n e.context = e.context.substring(context.length);\n }\n return e;\n };\n };\n \n \n Dom.ready(() => {\n document.querySelectorAll('label:not([data-error])').forEach(el => {\n el.dataset['error'] = \"Il valore inserito non è valido\";\n });\n });\n \n Dom.ready(() => {\n Dom.on(document.body, 'change', '[data-pattern]', {}, evt => {\n const el = evt.srcElement;\n const pattern = el.dataset['pattern'];\n const matches = el.value.match(pattern);\n const label = el.closest('label');\n if(label === null){\n return;\n }\n label.classList[matches ? 'remove' : 'add']('has-error'); \n });\n });\n */\nexport { Form };","class ContextInterceptor {\n constructor() {\n const context = document.querySelector(\"meta[name='context']\").getAttribute(\"content\");\n this.context = context.endsWith(\"/\") ? context.substring(0, context.length - 1) : context;\n }\n async intercept(request, chain){\n const separator = request.resource.startsWith(\"/\") ? \"\" : \"/\";\n request.resource = this.context + separator + request.resource;\n return await chain.proceed(request);\n }\n}\n\nclass CsrfTokenInterceptor {\n constructor() {\n this.k = document.querySelector(\"meta[name='_csrf_header']\").getAttribute(\"content\");\n this.v = document.querySelector(\"meta[name='_csrf']\").getAttribute(\"content\");\n }\n async intercept(request, chain){\n const headers = new Headers(request.options.headers);\n headers.set(this.k, this.v);\n request.options.headers = headers;\n return await chain.proceed(request);\n }\n}\n\nclass RedirectOnUnauthorizedInterceptor {\n constructor(redirectUri) {\n this.redirectUri = redirectUri;\n }\n async intercept(request, chain){\n const response = await chain.proceed(request);\n if (response.status !== 401) {\n return response;\n }\n window.location.href = redirectUri;\n }\n}\n\nclass Failure extends Error {\n static parseProblems(status, text) {\n const def = [{\n type: \"GENERIC_PROBLEM\",\n context: null,\n reason: `${status}: ${text}`,\n details: null\n }];\n try {\n return text ? JSON.parse(text) : def;\n } catch (e) {\n return def;\n }\n }\n static fromResponse(status, text) {\n return new Failure(status, Failure.parseProblems(status, text));\n }\n constructor(status, problems) {\n super(JSON.stringify(problems));\n this.name = `Failure:${status}`;\n this.status = status;\n this.problems = problems;\n }\n}\n\nclass HttpClientBuilder {\n constructor() {\n this.interceptors = [];\n }\n withContext() {\n this.interceptors.push(new ContextInterceptor());\n return this;\n }\n withCsrfToken() {\n this.interceptors.push(new CsrfTokenInterceptor());\n return this;\n }\n withRedirectOnUnauthorized(redirectUri) {\n this.interceptors.push(new RedirectOnUnauthorizedInterceptor(redirectUri));\n return this;\n }\n withInterceptors(...interceptors) {\n this.interceptors.push(...interceptors);\n return this;\n }\n build() {\n const interceptors = this.interceptors;\n return new HttpClient({interceptors});\n }\n}\n\nclass HttpCall {\n async intercept(request, chain){\n return await fetch(request.resource, request.options);\n } \n}\n\nclass HttpInterceptorChain {\n constructor(interceptors, current){\n this.interceptors = interceptors;\n this.current = current;\n }\n async proceed(request){\n const interceptor = this.interceptors[this.current];\n return await interceptor.intercept(request, new HttpInterceptorChain(this.interceptors, this.current + 1));\n }\n}\n\n\nclass HttpClient {\n static builder() {\n return new HttpClientBuilder();\n }\n constructor({interceptors}){\n this.interceptors = interceptors || [];\n }\n async fetch(resource, options) {\n const interceptors = [...this.interceptors, ...options.interceptors || [], new HttpCall()];\n const chain = new HttpInterceptorChain(interceptors, 0);\n return await chain.proceed({resource, options});\n }\n async json(resource, options) {\n try {\n const response = await this.fetch(resource, options);\n if (!response.ok) {\n const message = await response.text();\n throw Failure.fromResponse(response.status, message);\n }\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } catch (e) {\n if (e instanceof Failure) {\n throw e;\n }\n throw new Failure(0, [{\n type: \"CONNECTION_PROBLEM\",\n context: null,\n reason: e.message,\n details: null\n }]);\n }\n }\n async form(resource, options, uiOptions) {\n const ui = uiOptions || {};\n ui.buttons?.forEach(el => {\n el.setAttribute(\"disabled\", \"disabled\");\n if (ui.loader) {\n el.dataset['oldContent'] = el.innerHTML;\n el.innerHTML = ui.loader;\n }\n });\n try {\n const r = await this.json(resource, options);\n ui.form?.clearErrors();\n return r;\n } catch (e) {\n ui.form?.setErrors(e.problems);\n throw e;\n } finally {\n ui.buttons?.forEach(el => {\n el.removeAttribute(\"disabled\");\n el.innerHTML = el.dataset['oldContent'];\n delete el.dataset['oldContent'];\n });\n }\n }\n}\n\n\n\nexport { HttpClient, Failure };\n","\nclass Storage {\n constructor(prefix, storage) {\n this.prefix = prefix;\n this.storage = storage;\n }\n save(k, v) {\n this.storage.setItem(`${this.prefix}-${k}`, JSON.stringify(v));\n }\n load(k) {\n const got = this.storage.getItem(`${this.prefix}-${k}`);\n return got === undefined ? undefined : JSON.parse(got);\n }\n remove(k) {\n this.storage.removeItem(`${this.prefix}-${k}`);\n }\n pop(k) {\n const decoded = this.load(k);\n this.remove(k);\n return decoded;\n }\n}\n\nclass LocalStorage extends Storage {\n constructor(prefix) {\n super(prefix, localStorage);\n }\n}\n\nclass SessionStorage extends Storage {\n constructor(prefix) {\n super(prefix, sessionStorage);\n }\n}\n\nclass VersionedStorage {\n constructor(storage, key, dataSupplier){\n this.storage = storage;\n this.key = key;\n this.dataSupplier = dataSupplier;\n this.cache = null;\n \n }\n async load(revision){\n const saved = this.storage.load(this.key);\n if (!!saved && saved.revision === revision) {\n this.cache = saved.value;\n return;\n }\n const freshData = await this.dataSupplier(revision, this.key);\n this.storage.save(this.key, {\n revision: revision,\n value: freshData\n });\n this.cache = freshData;\n }\n data(){\n return this.cache;\n }\n}\n\n\n\nexport {LocalStorage, SessionStorage, VersionedStorage};","import { Base64 } from \"./encodings.mjs\";\nimport { SessionStorage } from \"./storage.mjs\";\n\n\nclass AuthorizationCodeFlow {\n static forKeycloak(clientId, realmBaseUrl, redirectUri){\n const scope = \"openid profile\";\n return new AuthorizationCodeFlow(clientId, scope, {\n auth: new URL(\"protocol/openid-connect/auth\", realmBaseUrl),\n token: new URL(\"protocol/openid-connect/token\", realmBaseUrl),\n logout: new URL(\"protocol/openid-connect/logout\", realmBaseUrl),\n registration: new URL(\"protocol/openid-connect/registrations\", realmBaseUrl),\n redirect: redirectUri\n }); \n }\n constructor(clientId, scope, {auth, token, registration, logout, redirect}) {\n this.storage = new SessionStorage(clientId);\n this.clientId = clientId;\n this.scope = scope;\n this.uri = {auth, token, registration, logout, redirect};\n }\n async action(uri, additionalParams){\n const pkceVerifier = Base64.encode(crypto.getRandomValues(new Uint8Array(32)).buffer);\n const pkceChallenge = Base64.encode(await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(pkceVerifier)));\n const state = this.clientId + Base64.encode(crypto.getRandomValues(new Uint8Array(16)).buffer);\n this.storage.save(AuthorizationCodeFlow.PKCE_AND_STATE_KEY, {\n state: state,\n verifier: pkceVerifier\n });\n const url = new URL(uri);\n url.searchParams.set(\"client_id\", this.clientId);\n url.searchParams.set(\"redirect_uri\", this.uri.redirect);\n url.searchParams.set(\"response_type\", 'code');\n url.searchParams.set(\"scope\", this.scope);\n url.searchParams.set(\"state\", state);\n url.searchParams.set(\"code_challenge\", pkceChallenge);\n url.searchParams.set(\"code_challenge_method\", 'S256');\n Object.entries(additionalParams || {}).forEach(kv => {\n url.searchParams.set(kv[0], kv[1]);\n });\n window.location = url;\n }\n async registration(additionalParams){\n await this.action(this.uri.registration, additionalParams);\n }\n async applicationInitiatedAction(kcAction){\n await this.action(this.uri.auth, {\n kc_action: kcAction\n });\n }\n async _tokenExchange(code, state) {\n window.history.replaceState('', \"\", this.uri.redirect);\n const stateAndVerifier = this.storage.pop(AuthorizationCodeFlow.PKCE_AND_STATE_KEY);\n if (stateAndVerifier.state !== state) {\n throw new Error(\"State mismatch\");\n }\n const response = await fetch(this.uri.token, {\n method: \"POST\",\n headers: {\n \"Content-Type\": 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams([\n [\"client_id\", this.clientId],\n [\"code\", code],\n [\"grant_type\", \"authorization_code\"],\n [\"code_verifier\", stateAndVerifier.verifier],\n [\"state\", stateAndVerifier.state],\n [\"redirect_uri\", this.uri.redirect]\n ])\n });\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\"Error:\" + response.status + \": \" + text);\n }\n const token = await response.json();\n return new AuthorizationCodeFlowSession(this.clientId, token, this.uri);\n }\n async ensureLoggedIn() {\n const url = new URL(window.location.href);\n const code = url.searchParams.get(\"code\");\n if (code && this.storage.load(AuthorizationCodeFlow.PKCE_AND_STATE_KEY)) {\n //if callback from keycloak and we have our state still stored\n const state = url.searchParams.get(\"state\");\n return await this._tokenExchange(code, state);\n }\n //if not authorized\n await this.action(this.uri.auth, {});\n return null;\n }\n}\nAuthorizationCodeFlow.PKCE_AND_STATE_KEY = \"state-and-verifier\";\n\nclass AuthorizationCodeFlowSession {\n static parseToken(token) {\n const [rawHeader, rawPayload, signature] = token.split(\".\");\n const ut8decoder = new TextDecoder(\"utf-8\");\n return {\n header: JSON.parse(ut8decoder.decode(Base64.decode(rawHeader, Base64.STANDARD))),\n payload: JSON.parse(ut8decoder.decode(Base64.decode(rawPayload, Base64.STANDARD))),\n signature: signature\n };\n } \n constructor(clientId, t, {token, logout, redirect}) {\n this.clientId = clientId;\n this.token = t;\n this.accessToken = AuthorizationCodeFlowSession.parseToken(t.access_token);\n this.refreshToken = AuthorizationCodeFlowSession.parseToken(t.refresh_token);\n this.uri = { token, logout, redirect }\n this.refreshCallback = null;\n }\n onRefresh(callback) {\n this.refreshCallback = callback;\n }\n async refresh() {\n const response = await fetch(this.uri.token, {\n method: \"POST\",\n headers: {\n \"Content-Type\": 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams([\n [\"client_id\", this.clientId],\n [\"grant_type\", \"refresh_token\"],\n [\"refresh_token\", this.token.refresh_token]\n ])\n });\n if (!response.ok) {\n throw new Error(\"Error:\" + response.code + \": \" + response.text());\n }\n const token = await response.json();\n this.token = token;\n this.accessToken = this._parseToken(token.access_token);\n this.refreshToken = this._parseToken(token.refresh_token);\n if (this.refreshCallback) {\n this.refreshCallback(this.token, this.accessToken, this.refreshToken);\n }\n }\n shouldBeRefreshed(gracePeriod) {\n const now = new Date().getTime();\n const refreshTokenExpiresAt = this.refreshToken.payload.exp * 1000;\n const expired = now > refreshTokenExpiresAt;\n const shouldRefresh = now - gracePeriod > refreshTokenExpiresAt;\n return !expired && shouldRefresh;\n }\n async refreshIf(gracePeriod) {\n if (!this.shouldBeRefreshed(gracePeriod)) {\n return;\n }\n await this.refresh();\n }\n logout() {\n const url = new URL(this.uri.logout);\n url.searchParams.set(\"post_logout_redirect_uri\", this.uri.redirect);\n url.searchParams.set(\"id_token_hint\", this.token.id_token);\n window.location = url;\n }\n\n bearerToken() {\n return `Bearer ${this.token.access_token}`;\n }\n \n interceptor(gracePeriodBefore, gracePeriodAfter){\n return new AuthorizationCodeFlowInterceptor(this, gracePeriodBefore, gracePeriodAfter); \n }\n}\n\nclass AuthorizationCodeFlowInterceptor {\n constructor(session, gracePeriodBefore, gracePeriodAfter) {\n this.session = session;\n this.gracePeriodBefore = gracePeriodBefore || 2000;\n this.gracePeriodAfter = gracePeriodAfter || 30000;\n }\n async intercept(request, chain) {\n await this.session.refreshIf(this.gracePeriodBefore);\n const headers = new Headers(request.options.headers);\n headers.set(\"Authorization\", this.session.bearerToken());\n request.options.headers = headers;\n const response = await chain.proceed(request);\n await this.session.refreshIf(this.gracePeriodAfter);\n return response;\n }\n}\n\n\nexport {AuthorizationCodeFlow, AuthorizationCodeFlowSession, AuthorizationCodeFlowInterceptor };","\nconst timing = {\n sleep(ms) {\n return new Promise(resolve => setTimeout(resolve, ms));\n },\n DEBOUNCE_DEFAULT: 0,\n DEBOUNCE_IMMEDIATE: 1,\n debounce(timeoutMs, func, options) {\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n let opts = options || timing.DEBOUNCE_DEFAULT;\n\n const later = () => {\n const elapsed = new Date().getTime() - previousTimestamp;\n if (timeoutMs > elapsed) {\n tid = setTimeout(later, timeoutMs - elapsed);\n return;\n }\n tid = null;\n if (opts !== timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n // This check is needed because `func` can recursively invoke `debounced`.\n if (tid === null) {\n args = [];\n }\n };\n\n return function () {\n args = arguments;\n previousTimestamp = new Date().getTime();\n if (tid === null) {\n tid = setTimeout(later, timeoutMs);\n if (opts === timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n }\n };\n },\n THROTTLE_DEFAULT: 0,\n THROTTLE_NO_LEADING: 1,\n THROTTLE_NO_TRAILING: 2,\n throttle(timeoutMs, func, options) {\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n let opts = options || timing.THROTTLE_DEFAULT;\n\n const later = () => {\n previousTimestamp = (opts & timing.THROTTLE_NO_LEADING) ? 0 : new Date().getTime();\n tid = null;\n func(...args);\n if (tid === null) {\n args = [];\n }\n };\n\n return function () {\n const now = new Date().getTime();\n if (!previousTimestamp && (opts & timing.THROTTLE_NO_LEADING)) {\n previousTimestamp = now;\n }\n const remaining = timeoutMs - (now - previousTimestamp);\n args = arguments;\n if (remaining <= 0 || remaining > timeoutMs) {\n if (tid !== null) {\n clearTimeout(tid);\n tid = null;\n }\n previousTimestamp = now;\n func(...args);\n if (tid === null) {\n args = [];\n }\n } else if (tid === null && !(opts & timing.THROTTLE_NO_TRAILING)) {\n tid = setTimeout(later, remaining);\n }\n };\n\n }\n};\n\n\nexport { timing };","class Wizard {\n constructor(el) {\n this.el = el;\n this.progress = [...el.children].filter(e => e.matches(\"header,ol,ul\"));\n\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n if (current === undefined && children.length > 0) {\n children[0].classList.add('active');\n }\n });\n if (this.el.querySelector('section.current') === null) {\n const firstSection = this.el.querySelector('section:first-of-type');\n if (firstSection !== null) {\n firstSection.classList.add('current');\n }\n }\n }\n next() {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n current?.nextElementSibling?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection.classList.remove(\"current\");\n currentSection.nextElementSibling.classList.add('current');\n\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n\n }\n prev() {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n current?.previousElementSibling?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection.classList.remove(\"current\");\n currentSection.previousElementSibling.classList.add('current');\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n }\n moveTo = function (n) {\n this.progress.forEach(p => {\n const children = [...p.children];\n const current = children.filter(e => e.matches(\".active\"))[0];\n current?.classList.remove('active');\n p.children[+n]?.classList.add('active');\n });\n const currentSection = this.el.querySelector('section.current');\n currentSection?.classList.remove(\"current\");\n const nthSection = this.el.querySelector(`section:nth-child(${+n})`);\n nthSection.classList.add('current');\n this.el.dispatchEvent(new CustomEvent('wizard:activate', {\n bubbles: true,\n cancelable: true\n }));\n }\n}\n\n\n\n\nexport { Wizard };\n","class App {\n constructor() {\n this.configurers = [];\n this.initializers = [];\n this.handlers = [];\n this.running = false;\n document.addEventListener(\"DOMContentLoaded\", async () => {\n await Promise.all(this.configurers);\n await Promise.all(this.initializers.map(h => Promise.resolve(h())));\n await Promise.all(this.handlers.map(h => Promise.resolve(h())));\n });\n }\n configure(cb) {\n this.configurers.push(Promise.resolve(cb()));\n return this;\n }\n initialize(cb) {\n this.initializers.push(cb);\n return this;\n }\n ready(cb) {\n this.handlers.push(cb);\n return this;\n }\n}\n\nexport { App };\n"],"names":["mutate","mutators","el","raw","key","values","maybeMutator","dataset","getAttribute","value","checked","Bindings","constructor","extractors","ignoredChildrenSelector","valueHoldersSelector","this","setValues","k","hasOwnProperty","Array","from","querySelectorAll","CSS","escape","forEach","getValues","filter","closest","reduce","result","path","keys","split","map","match","current","previous","i","ckey","pkey","Number","isInteger","isArray","length","undefined","providePath","maybeExtractor","extract","Base64","static","arrayBuffer","dialect","d","URL_SAFE","len","byteLength","view","Uint8Array","res","substring","str","nbytes","Math","floor","vi","si","v1","indexOf","charAt","v2","v3","v4","buffer","STANDARD","Hex","hex","Error","lenInBytes","e","offset","octet","parseInt","bytes","upper","b","toString","toUpperCase","o","padStart","join","Form","bindings","globalErrorsEl","fieldContainerSelector","errorClass","hideClass","DEFAULT_FIELD_CONTAINER_SELECTOR","DEFAULT_ERROR_CLASS","DEFAULT_HIDE_CLASS","setErrors","errors","scrollFirstErrorIntoView","context","clearErrors","mapError","type","name","replace","label","classList","add","reason","globalErrors","innerHTML","remove","yOffsets","getBoundingClientRect","y","window","scrollY","firstErrorScrollY","min","Infinity","scroll","scrollX","l","ContextInterceptor","document","querySelector","endsWith","async","request","chain","separator","resource","startsWith","proceed","CsrfTokenInterceptor","v","headers","Headers","options","set","RedirectOnUnauthorizedInterceptor","redirectUri","response","status","location","href","Failure","text","def","details","JSON","parse","parseProblems","problems","super","stringify","HttpClientBuilder","interceptors","withContext","push","withCsrfToken","withRedirectOnUnauthorized","withInterceptors","build","HttpClient","HttpCall","fetch","HttpInterceptorChain","interceptor","intercept","ok","message","fromResponse","uiOptions","ui","buttons","setAttribute","loader","r","json","form","removeAttribute","Storage","prefix","storage","save","setItem","load","got","getItem","removeItem","pop","decoded","LocalStorage","localStorage","SessionStorage","sessionStorage","VersionedStorage","dataSupplier","cache","revision","saved","freshData","data","AuthorizationCodeFlow","clientId","realmBaseUrl","auth","URL","token","logout","registration","redirect","scope","uri","additionalParams","pkceVerifier","encode","crypto","getRandomValues","pkceChallenge","subtle","digest","TextEncoder","state","PKCE_AND_STATE_KEY","verifier","url","searchParams","Object","entries","kv","action","kcAction","kc_action","code","history","replaceState","stateAndVerifier","method","body","URLSearchParams","AuthorizationCodeFlowSession","get","_tokenExchange","rawHeader","rawPayload","signature","ut8decoder","TextDecoder","header","decode","payload","t","accessToken","parseToken","access_token","refreshToken","refresh_token","refreshCallback","onRefresh","callback","_parseToken","shouldBeRefreshed","gracePeriod","now","Date","getTime","refreshTokenExpiresAt","exp","refresh","id_token","bearerToken","gracePeriodBefore","gracePeriodAfter","AuthorizationCodeFlowInterceptor","session","refreshIf","timing","sleep","ms","Promise","resolve","setTimeout","DEBOUNCE_DEFAULT","DEBOUNCE_IMMEDIATE","debounce","timeoutMs","func","tid","args","previousTimestamp","opts","later","elapsed","arguments","THROTTLE_DEFAULT","THROTTLE_NO_LEADING","THROTTLE_NO_TRAILING","throttle","remaining","clearTimeout","Wizard","progress","children","matches","p","firstSection","next","nextElementSibling","currentSection","dispatchEvent","CustomEvent","bubbles","cancelable","prev","previousElementSibling","moveTo","n","App","configurers","initializers","handlers","running","addEventListener","all","h","configure","cb","initialize","ready"],"mappings":"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"}
package/dist/ful.mjs CHANGED
@@ -238,9 +238,10 @@ class ContextInterceptor {
238
238
  const context = document.querySelector("meta[name='context']").getAttribute("content");
239
239
  this.context = context.endsWith("/") ? context.substring(0, context.length - 1) : context;
240
240
  }
241
- before(request) {
241
+ async intercept(request, chain){
242
242
  const separator = request.resource.startsWith("/") ? "" : "/";
243
243
  request.resource = this.context + separator + request.resource;
244
+ return await chain.proceed(request);
244
245
  }
245
246
  }
246
247
 
@@ -249,10 +250,11 @@ class CsrfTokenInterceptor {
249
250
  this.k = document.querySelector("meta[name='_csrf_header']").getAttribute("content");
250
251
  this.v = document.querySelector("meta[name='_csrf']").getAttribute("content");
251
252
  }
252
- before(request) {
253
+ async intercept(request, chain){
253
254
  const headers = new Headers(request.options.headers);
254
255
  headers.set(this.k, this.v);
255
256
  request.options.headers = headers;
257
+ return await chain.proceed(request);
256
258
  }
257
259
  }
258
260
 
@@ -260,9 +262,10 @@ class RedirectOnUnauthorizedInterceptor {
260
262
  constructor(redirectUri) {
261
263
  this.redirectUri = redirectUri;
262
264
  }
263
- after(request, response) {
265
+ async intercept(request, chain){
266
+ const response = await chain.proceed(request);
264
267
  if (response.status !== 401) {
265
- return;
268
+ return response;
266
269
  }
267
270
  window.location.href = redirectUri;
268
271
  }
@@ -319,31 +322,35 @@ class HttpClientBuilder {
319
322
  }
320
323
  }
321
324
 
325
+ class HttpCall {
326
+ async intercept(request, chain){
327
+ return await fetch(request.resource, request.options);
328
+ }
329
+ }
330
+
331
+ class HttpInterceptorChain {
332
+ constructor(interceptors, current){
333
+ this.interceptors = interceptors;
334
+ this.current = current;
335
+ }
336
+ async proceed(request){
337
+ const interceptor = this.interceptors[this.current];
338
+ return await interceptor.intercept(request, new HttpInterceptorChain(this.interceptors, this.current + 1));
339
+ }
340
+ }
341
+
342
+
322
343
  class HttpClient {
323
344
  static builder() {
324
345
  return new HttpClientBuilder();
325
346
  }
326
- constructor( {interceptors}){
347
+ constructor({interceptors}){
327
348
  this.interceptors = interceptors || [];
328
349
  }
329
350
  async fetch(resource, options) {
330
- const is = this.interceptors.concat(options.interceptors || []);
331
- const request = {resource, options};
332
- await is.forEach(async (i) => {
333
- if (!i.before) {
334
- return;
335
- }
336
- await i.before(request);
337
- });
338
- const response = await fetch(request.resource, request.options);
339
- await is.forEach(async (i) => {
340
- if (!i.after) {
341
- return;
342
- }
343
- await i.after(request, response);
344
- });
345
-
346
- return response;
351
+ const interceptors = [...this.interceptors, ...options.interceptors || [], new HttpCall()];
352
+ const chain = new HttpInterceptorChain(interceptors, 0);
353
+ return await chain.proceed({resource, options});
347
354
  }
348
355
  async json(resource, options) {
349
356
  try {
@@ -454,22 +461,22 @@ class VersionedStorage {
454
461
 
455
462
  class AuthorizationCodeFlow {
456
463
  static forKeycloak(clientId, realmBaseUrl, redirectUri){
457
- const authUri = new URL("protocol/openid-connect/auth", realmBaseUrl);
458
- const tokenUri = new URL("protocol/openid-connect/token", realmBaseUrl);
459
- const logoutUri = new URL("protocol/openid-connect/logout", realmBaseUrl);
460
464
  const scope = "openid profile";
461
- return new AuthorizationCodeFlow(clientId, scope, authUri, tokenUri, logoutUri, redirectUri);
462
- }
463
- constructor(clientId, scope, authUri, tokenUri, logoutUri, redirectUri) {
465
+ return new AuthorizationCodeFlow(clientId, scope, {
466
+ auth: new URL("protocol/openid-connect/auth", realmBaseUrl),
467
+ token: new URL("protocol/openid-connect/token", realmBaseUrl),
468
+ logout: new URL("protocol/openid-connect/logout", realmBaseUrl),
469
+ registration: new URL("protocol/openid-connect/registrations", realmBaseUrl),
470
+ redirect: redirectUri
471
+ });
472
+ }
473
+ constructor(clientId, scope, {auth, token, registration, logout, redirect}) {
474
+ this.storage = new SessionStorage(clientId);
464
475
  this.clientId = clientId;
465
476
  this.scope = scope;
466
- this.authUri = authUri;
467
- this.tokenUri = tokenUri;
468
- this.logoutUri = logoutUri;
469
- this.redirectUri = redirectUri;
470
- this.storage = new SessionStorage(clientId);
477
+ this.uri = {auth, token, registration, logout, redirect};
471
478
  }
472
- async _auth() {
479
+ async action(uri, additionalParams){
473
480
  const pkceVerifier = Base64.encode(crypto.getRandomValues(new Uint8Array(32)).buffer);
474
481
  const pkceChallenge = Base64.encode(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(pkceVerifier)));
475
482
  const state = this.clientId + Base64.encode(crypto.getRandomValues(new Uint8Array(16)).buffer);
@@ -477,23 +484,34 @@ class AuthorizationCodeFlow {
477
484
  state: state,
478
485
  verifier: pkceVerifier
479
486
  });
480
- const url = new URL(this.authUri);
487
+ const url = new URL(uri);
481
488
  url.searchParams.set("client_id", this.clientId);
482
- url.searchParams.set("redirect_uri", this.redirectUri);
489
+ url.searchParams.set("redirect_uri", this.uri.redirect);
483
490
  url.searchParams.set("response_type", 'code');
484
491
  url.searchParams.set("scope", this.scope);
485
492
  url.searchParams.set("state", state);
486
493
  url.searchParams.set("code_challenge", pkceChallenge);
487
494
  url.searchParams.set("code_challenge_method", 'S256');
495
+ Object.entries(additionalParams || {}).forEach(kv => {
496
+ url.searchParams.set(kv[0], kv[1]);
497
+ });
488
498
  window.location = url;
489
499
  }
500
+ async registration(additionalParams){
501
+ await this.action(this.uri.registration, additionalParams);
502
+ }
503
+ async applicationInitiatedAction(kcAction){
504
+ await this.action(this.uri.auth, {
505
+ kc_action: kcAction
506
+ });
507
+ }
490
508
  async _tokenExchange(code, state) {
491
- window.history.replaceState('', "", this.redirectUri);
509
+ window.history.replaceState('', "", this.uri.redirect);
492
510
  const stateAndVerifier = this.storage.pop(AuthorizationCodeFlow.PKCE_AND_STATE_KEY);
493
511
  if (stateAndVerifier.state !== state) {
494
512
  throw new Error("State mismatch");
495
513
  }
496
- const response = await fetch(this.tokenUri, {
514
+ const response = await fetch(this.uri.token, {
497
515
  method: "POST",
498
516
  headers: {
499
517
  "Content-Type": 'application/x-www-form-urlencoded'
@@ -504,7 +522,7 @@ class AuthorizationCodeFlow {
504
522
  ["grant_type", "authorization_code"],
505
523
  ["code_verifier", stateAndVerifier.verifier],
506
524
  ["state", stateAndVerifier.state],
507
- ["redirect_uri", this.redirectUri]
525
+ ["redirect_uri", this.uri.redirect]
508
526
  ])
509
527
  });
510
528
  if (!response.ok) {
@@ -512,7 +530,7 @@ class AuthorizationCodeFlow {
512
530
  throw new Error("Error:" + response.status + ": " + text);
513
531
  }
514
532
  const token = await response.json();
515
- return new AuthorizationCodeFlowSession(this.clientId, token, this.tokenUri, this.logoutUri, this.redirectUri);
533
+ return new AuthorizationCodeFlowSession(this.clientId, token, this.uri);
516
534
  }
517
535
  async ensureLoggedIn() {
518
536
  const url = new URL(window.location.href);
@@ -523,7 +541,7 @@ class AuthorizationCodeFlow {
523
541
  return await this._tokenExchange(code, state);
524
542
  }
525
543
  //if not authorized
526
- await this._auth();
544
+ await this.action(this.uri.auth, {});
527
545
  return null;
528
546
  }
529
547
  }
@@ -532,27 +550,26 @@ AuthorizationCodeFlow.PKCE_AND_STATE_KEY = "state-and-verifier";
532
550
  class AuthorizationCodeFlowSession {
533
551
  static parseToken(token) {
534
552
  const [rawHeader, rawPayload, signature] = token.split(".");
553
+ const ut8decoder = new TextDecoder("utf-8");
535
554
  return {
536
- header: JSON.parse(atob(rawHeader)),
537
- payload: JSON.parse(atob(rawPayload)),
555
+ header: JSON.parse(ut8decoder.decode(Base64.decode(rawHeader, Base64.STANDARD))),
556
+ payload: JSON.parse(ut8decoder.decode(Base64.decode(rawPayload, Base64.STANDARD))),
538
557
  signature: signature
539
558
  };
540
559
  }
541
- constructor(clientId, token, tokenUri, logoutUri, redirectUri) {
560
+ constructor(clientId, t, {token, logout, redirect}) {
542
561
  this.clientId = clientId;
543
- this.token = token;
544
- this.tokenUri = tokenUri;
545
- this.logoutUri = logoutUri;
546
- this.redirectUri = redirectUri;
547
- this.accessToken = AuthorizationCodeFlowSession.parseToken(token.access_token);
548
- this.refreshToken = AuthorizationCodeFlowSession.parseToken(token.refresh_token);
562
+ this.token = t;
563
+ this.accessToken = AuthorizationCodeFlowSession.parseToken(t.access_token);
564
+ this.refreshToken = AuthorizationCodeFlowSession.parseToken(t.refresh_token);
565
+ this.uri = { token, logout, redirect };
549
566
  this.refreshCallback = null;
550
567
  }
551
568
  onRefresh(callback) {
552
569
  this.refreshCallback = callback;
553
570
  }
554
571
  async refresh() {
555
- const response = await fetch(this.tokenUri, {
572
+ const response = await fetch(this.uri.token, {
556
573
  method: "POST",
557
574
  headers: {
558
575
  "Content-Type": 'application/x-www-form-urlencoded'
@@ -588,8 +605,8 @@ class AuthorizationCodeFlowSession {
588
605
  await this.refresh();
589
606
  }
590
607
  logout() {
591
- const url = new URL(this.logoutUri);
592
- url.searchParams.set("post_logout_redirect_uri", this.redirectUri);
608
+ const url = new URL(this.uri.logout);
609
+ url.searchParams.set("post_logout_redirect_uri", this.uri.redirect);
593
610
  url.searchParams.set("id_token_hint", this.token.id_token);
594
611
  window.location = url;
595
612
  }
@@ -609,13 +626,12 @@ class AuthorizationCodeFlowInterceptor {
609
626
  this.gracePeriodBefore = gracePeriodBefore || 2000;
610
627
  this.gracePeriodAfter = gracePeriodAfter || 30000;
611
628
  }
612
- async before(request) {
629
+ async intercept(request, chain) {
613
630
  await this.session.refreshIf(this.gracePeriodBefore);
614
631
  const headers = new Headers(request.options.headers);
615
632
  headers.set("Authorization", this.session.bearerToken());
616
- return request;
617
- }
618
- async after(request, response) {
633
+ request.options.headers = headers;
634
+ const response = await chain.proceed(request);
619
635
  await this.session.refreshIf(this.gracePeriodAfter);
620
636
  return response;
621
637
  }