solid-logic 4.0.8-3 → 4.0.8-4

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.
Files changed (33) hide show
  1. package/dist/authn/SolidAuthnLogic.cjs.js +1 -1
  2. package/dist/authn/SolidAuthnLogic.cjs.js.map +1 -1
  3. package/dist/authn/SolidAuthnLogic.esm.js +4 -4
  4. package/dist/authn/SolidAuthnLogic.esm.js.map +1 -1
  5. package/dist/logic/solidLogic.cjs.js +1 -1
  6. package/dist/logic/solidLogic.cjs.js.map +1 -1
  7. package/dist/logic/solidLogic.esm.js +28 -26
  8. package/dist/logic/solidLogic.esm.js.map +1 -1
  9. package/dist/resource/resourceHttp.cjs.js +2 -0
  10. package/dist/resource/resourceHttp.cjs.js.map +1 -0
  11. package/dist/resource/resourceHttp.esm.js +21 -0
  12. package/dist/resource/resourceHttp.esm.js.map +1 -0
  13. package/dist/resource/resourceLogic.cjs.js +2 -0
  14. package/dist/resource/resourceLogic.cjs.js.map +1 -0
  15. package/dist/resource/resourceLogic.esm.js +130 -0
  16. package/dist/resource/resourceLogic.esm.js.map +1 -0
  17. package/dist/resource/resourceMetadata.cjs.js +2 -0
  18. package/dist/resource/resourceMetadata.cjs.js.map +1 -0
  19. package/dist/resource/resourceMetadata.esm.js +28 -0
  20. package/dist/resource/resourceMetadata.esm.js.map +1 -0
  21. package/dist/typeIndex/typeIndexLogic.cjs.js +1 -1
  22. package/dist/typeIndex/typeIndexLogic.cjs.js.map +1 -1
  23. package/dist/typeIndex/typeIndexLogic.esm.js +67 -42
  24. package/dist/typeIndex/typeIndexLogic.esm.js.map +1 -1
  25. package/dist/util/containerLogic.cjs.js +1 -1
  26. package/dist/util/containerLogic.cjs.js.map +1 -1
  27. package/dist/util/containerLogic.esm.js +23 -18
  28. package/dist/util/containerLogic.esm.js.map +1 -1
  29. package/dist/util/utilityLogic.cjs.js +2 -2
  30. package/dist/util/utilityLogic.cjs.js.map +1 -1
  31. package/dist/util/utilityLogic.esm.js +57 -71
  32. package/dist/util/utilityLogic.esm.js.map +1 -1
  33. package/package.json +1 -1
@@ -1,2 +1,2 @@
1
- const e=require("../util/debug.cjs.js"),t=require("./authUtil.cjs.js");let n=require("rdflib");var r=5e3;async function i(e){if(e===null)return;let t,n=new Promise(e=>{t=setTimeout(()=>e(void 0),r)});try{return await Promise.race([e,n])}finally{t!==void 0&&clearTimeout(t)}}var a=class{constructor(e){this.checkUserInFlight=null,this.sessionRestoreHookAttached=!1,this.fallbackWebId=null,this.session=e}get authSession(){return this.session}currentUser(){let e=t.appContext();if(e.viewingNoAuthPage)return(0,n.sym)(e.webId);let r=this.session,i=r?.info?.webId,a=r?.webId,o=i||a||this.fallbackWebId,s=r?.info?.isLoggedIn,c=r?.isActive,l=s===!0||c===!0||(s==null&&c==null?!!o:!1)||!!this.fallbackWebId;return this&&this.session&&o&&l?(0,n.sym)(o):t.offlineTestID()}async checkUser(t){let n=new URL(window.location.href).hash;n&&window.localStorage.setItem(`preLoginRedirectHash`,n);let r=this.session;!this.sessionRestoreHookAttached&&typeof r?.events?.on==`function`&&(r.events.on(`sessionRestore`,t=>{e.log(`Session restored to ${t}`),document.location.toString()!==t&&history.replaceState(null,``,t)}),this.sessionRestoreHookAttached=!0),this.checkUserInFlight||=this.resolveCurrentUser();let i=this.checkUserInFlight,a;try{a=await i}finally{this.checkUserInFlight===i&&(this.checkUserInFlight=null)}return Promise.resolve(t?t(a):a)}async resolveCurrentUser(){let n=this.session,r=new URL(window.location.href);if(r.hash=``,typeof n?.handleIncomingRedirect==`function`)await n.handleIncomingRedirect({restorePreviousSession:!0,url:r.href});else{let t=n?.isActive??!!n?.webId;if(typeof n?.restore==`function`){try{await i(n.restore())}catch(t){let n=t instanceof Error?t.message:String(t);if(!/no session to restore/i.test(n))throw t;e.log(`No previous session to restore`)}let r=n?.isActive??!!n?.webId;!t&&r&&n.events?.emit(`sessionRestore`,window.location.href)}if(typeof n?.handleRedirectFromLogin==`function`){let e=n?.isActive??!!n?.webId;await n.handleRedirectFromLogin();let t=n?.isActive??!!n?.webId;!e&&t&&n.events?.emit(`login`)}}let a=window.localStorage.getItem(`preLoginRedirectHash`);if(a){let e=new URL(window.location.href);e.hash!==a&&(history.pushState?history.pushState(null,document.title,a):location.hash=a,e.hash=a),window.localStorage.setItem(`preLoginRedirectHash`,``)}let o=t.offlineTestID();if(o)return o;let s=this.webIdFromSession(n?.info,n);return s||=await this.probeNssCookieBackedWebId(),s?this.fallbackWebId=s:this.fallbackWebId=null,s&&(o=this.saveUser(s)),o&&e.log(`(Logged in as ${o} by authentication)`),o}async probeNssCookieBackedWebId(){if(typeof window>`u`)return null;let{hostname:e,port:t,protocol:n}=window.location;if(!e.endsWith(`.localhost`))return null;let r=e.slice(0,-10);if(!r||r===`localhost`||r.includes(`.`))return null;try{return(await fetch(`/account/password/change`,{credentials:`include`,redirect:`manual`,cache:`no-store`})).status===403?`${`${n}//${e}${t?`:${t}`:``}`}/profile/card#me`:null}catch{return null}}saveUser(e,t){let r;if(e){r=typeof e==`string`?e:e.uri;let i=(0,n.namedNode)(r);return t&&(t.me=i),i}return null}webIdFromSession(e,t){let n=e?.webId||t?.webId;if(!n)return null;let r=e?.isLoggedIn,i=t?.isLoggedIn,a=t?.isActive;return r===!0||i===!0||a===!0?n:r===!1&&i===!1&&a===!1?null:n}};exports.SolidAuthnLogic=a;
1
+ const e=require("../util/debug.cjs.js"),t=require("./authUtil.cjs.js");let n=require("rdflib");var r=5e3;async function i(e){if(e===null)return;let t,n=new Promise(e=>{t=setTimeout(()=>e(void 0),r)});try{return await Promise.race([e,n])}finally{t!==void 0&&clearTimeout(t)}}var a=class{constructor(e){this.checkUserInFlight=null,this.sessionRestoreHookAttached=!1,this.fallbackWebId=null,this.session=e}get authSession(){return this.session}currentUser(){let e=t.appContext();if(e.viewingNoAuthPage)return(0,n.sym)(e.webId);let r=this.session,i=r?.info?.webId,a=r?.webId,o=i||a||this.fallbackWebId,s=r?.info?.isLoggedIn,c=r?.isActive,l=s===!0||c===!0||(s==null&&c==null?!!o:!1)||!!this.fallbackWebId;return this&&this.session&&o&&l?(0,n.sym)(o):t.offlineTestID()}async checkUser(t){let n=new URL(window.location.href).hash;n&&window.localStorage.setItem(`preLoginRedirectHash`,n);let r=this.session;!this.sessionRestoreHookAttached&&typeof r?.events?.on==`function`&&(r.events.on(`sessionRestore`,t=>{e.log(`Session restored to ${t}`),document.location.toString()!==t&&history.replaceState(null,``,t)}),this.sessionRestoreHookAttached=!0),this.checkUserInFlight||=this.resolveCurrentUser();let i=this.checkUserInFlight,a;try{a=await i}finally{this.checkUserInFlight===i&&(this.checkUserInFlight=null)}return Promise.resolve(t?t(a):a)}async resolveCurrentUser(){let n=this.session,r=new URL(window.location.href);if(r.hash=``,typeof n?.handleIncomingRedirect==`function`)await n.handleIncomingRedirect({restorePreviousSession:!0,url:r.href});else{let t=n?.isActive??!!n?.webId;if(typeof n?.restore==`function`){try{await i(n.restore())}catch(t){let r=t instanceof Error?t.message:String(t);if((n?.isActive??!!n?.webId)&&!/no session to restore/i.test(r))throw t;e.log(`Session restore failed, continuing logged-out: ${r}`)}let r=n?.isActive??!!n?.webId;!t&&r&&n.events?.emit(`sessionRestore`,window.location.href)}if(typeof n?.handleRedirectFromLogin==`function`){let e=n?.isActive??!!n?.webId;await n.handleRedirectFromLogin();let t=n?.isActive??!!n?.webId;!e&&t&&n.events?.emit(`login`)}}let a=window.localStorage.getItem(`preLoginRedirectHash`);if(a){let e=new URL(window.location.href);e.hash!==a&&(history.pushState?history.pushState(null,document.title,a):location.hash=a,e.hash=a),window.localStorage.setItem(`preLoginRedirectHash`,``)}let o=t.offlineTestID();if(o)return o;let s=this.webIdFromSession(n?.info,n);return s||=await this.probeNssCookieBackedWebId(),s?this.fallbackWebId=s:this.fallbackWebId=null,s&&(o=this.saveUser(s)),o&&e.log(`(Logged in as ${o} by authentication)`),o}async probeNssCookieBackedWebId(){if(typeof window>`u`)return null;let{hostname:e,port:t,protocol:n}=window.location;if(!e.endsWith(`.localhost`))return null;let r=e.slice(0,-10);if(!r||r===`localhost`||r.includes(`.`))return null;try{return(await fetch(`/account/password/change`,{credentials:`include`,redirect:`manual`,cache:`no-store`})).status===403?`${`${n}//${e}${t?`:${t}`:``}`}/profile/card#me`:null}catch{return null}}saveUser(e,t){let r;if(e){r=typeof e==`string`?e:e.uri;let i=(0,n.namedNode)(r);return t&&(t.me=i),i}return null}webIdFromSession(e,t){let n=e?.webId||t?.webId;if(!n)return null;let r=e?.isLoggedIn,i=t?.isLoggedIn,a=t?.isActive;return r===!0||i===!0||a===!0?n:r===!1&&i===!1&&a===!1?null:n}};exports.SolidAuthnLogic=a;
2
2
  //# sourceMappingURL=SolidAuthnLogic.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SolidAuthnLogic.cjs.js","names":[],"sources":["../../src/authn/SolidAuthnLogic.ts"],"sourcesContent":["import { namedNode, NamedNode, sym } from 'rdflib'\nimport { appContext, offlineTestID } from './authUtil'\nimport * as debug from '../util/debug'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport type { AuthenticationContext, AuthnLogic } from '../types'\n\n// Some auth clients (uvdsl worker-backed session) only settle restore() on\n// a worker message; a missing/unreachable RefreshWorker asset makes it hang\n// forever. This caps the wait so the login UI can never spin indefinitely.\nconst SESSION_RESTORE_TIMEOUT_MS = 5000\n\n/**\n * Await a session restore promise, but give up after\n * SESSION_RESTORE_TIMEOUT_MS and resolve with undefined so callers can\n * treat a stalled restore as \"no previous session\".\n */\nasync function withRestoreTimeout<T> (promise: Promise<T> | null): Promise<T | undefined> {\n if (promise === null) return undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<undefined>(resolve => {\n timer = setTimeout(() => resolve(undefined), SESSION_RESTORE_TIMEOUT_MS)\n })\n try {\n return await Promise.race([promise, timeout])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n }\n}\n\nexport class SolidAuthnLogic implements AuthnLogic {\n private session: SessionWithLegacyEvents\n private checkUserInFlight: Promise<NamedNode | null> | null = null\n private sessionRestoreHookAttached = false\n private fallbackWebId: string | null = null\n\n constructor(solidAuthSession: SessionWithLegacyEvents) {\n this.session = solidAuthSession\n }\n\n // we created authSession getter because we want to access it as authn.authSession externally\n get authSession(): SessionWithLegacyEvents { return this.session }\n\n currentUser(): NamedNode | null {\n const app = appContext()\n if (app.viewingNoAuthPage) {\n return sym(app.webId)\n }\n const sessionAny = this.session as any\n const infoWebId = sessionAny?.info?.webId\n const sessionWebId = sessionAny?.webId\n const webId = infoWebId || sessionWebId || this.fallbackWebId\n const infoLoggedIn = sessionAny?.info?.isLoggedIn\n const sessionActive = sessionAny?.isActive\n const isLoggedIn = infoLoggedIn === true || sessionActive === true ||\n ((infoLoggedIn == null && sessionActive == null) ? Boolean(webId) : false) ||\n Boolean(this.fallbackWebId)\n if (this && this.session && webId && isLoggedIn) {\n return sym(webId)\n }\n return offlineTestID() // null unless testing\n }\n\n /**\n * Retrieves currently logged in webId from either\n * defaultTestUser or SolidAuth\n * Also activates a session after login\n * @param [setUserCallback] Optional callback\n * @returns Resolves with webId uri, if no callback provided\n */\n async checkUser<T> (\n setUserCallback?: (me: NamedNode | null) => T\n ): Promise<NamedNode | T | null> {\n // Save hash for \"restorePreviousSession\"\n const preLoginRedirectHash = new URL(window.location.href).hash\n if (preLoginRedirectHash) {\n window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)\n }\n const sessionAny = this.session as any\n if (!this.sessionRestoreHookAttached && typeof sessionAny?.events?.on === 'function') {\n // Backward-compatible hook for auth clients exposing an EventEmitter-style API.\n sessionAny.events.on('sessionRestore', (url: string) => {\n debug.log(`Session restored to ${url}`)\n if (document.location.toString() !== url) history.replaceState(null, '', url)\n })\n this.sessionRestoreHookAttached = true\n }\n\n if (!this.checkUserInFlight) {\n this.checkUserInFlight = this.resolveCurrentUser()\n }\n\n const inFlight = this.checkUserInFlight\n let me: NamedNode | null\n try {\n me = await inFlight\n } finally {\n if (this.checkUserInFlight === inFlight) {\n this.checkUserInFlight = null\n }\n }\n\n return Promise.resolve(setUserCallback ? setUserCallback(me) : me)\n }\n\n private async resolveCurrentUser (): Promise<NamedNode | null> {\n const sessionAny = this.session as any\n\n /**\n * Handle a successful authentication redirect\n */\n const redirectUrl = new URL(window.location.href)\n redirectUrl.hash = ''\n if (typeof sessionAny?.handleIncomingRedirect === 'function') {\n await sessionAny.handleIncomingRedirect({\n restorePreviousSession: true,\n url: redirectUrl.href\n })\n } else {\n // uvdsl-style session (no handleIncomingRedirect): restore then handle redirect.\n //\n // The worker-backed session (WebWorkerSession) resolves restore() ONLY\n // when the SharedWorker posts a message back. If the worker asset can't\n // be fetched — local/dev servers that don't serve the RefreshWorker\n // chunk at the resolved URL, wrong MIME type, CSP, or a worker that\n // fails before `onconnect` — the promise never settles and the login\n // UI would spin forever. Race it against a timeout and treat a stall\n // as \"no previous session\" so the page can render the login button.\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (typeof sessionAny?.restore === 'function') {\n try {\n await withRestoreTimeout(sessionAny.restore())\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n if (!/no session to restore/i.test(message)) {\n throw error\n }\n debug.log('No previous session to restore')\n }\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('sessionRestore', window.location.href)\n }\n }\n if (typeof sessionAny?.handleRedirectFromLogin === 'function') {\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n await sessionAny.handleRedirectFromLogin()\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('login')\n }\n }\n }\n\n // Check to see if a hash was stored in local storage\n const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')\n if (postLoginRedirectHash) {\n const curUrl = new URL(window.location.href)\n if (curUrl.hash !== postLoginRedirectHash) {\n if (history.pushState) {\n // debug.log('Setting window.location.has using pushState')\n history.pushState(null, document.title, postLoginRedirectHash)\n } else {\n // debug.warn('Setting window.location.has using location.hash')\n location.hash = postLoginRedirectHash\n }\n curUrl.hash = postLoginRedirectHash\n }\n // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document\n // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location\n window.localStorage.setItem('preLoginRedirectHash', '')\n }\n\n // Check to see if already logged in / have the WebID\n let me = offlineTestID()\n if (me) {\n return me\n }\n\n let webId = this.webIdFromSession(sessionAny?.info, sessionAny)\n if (!webId) {\n // NSS-specific fallback: recover WebID from NSS cookie session when client restore is empty.\n webId = await this.probeNssCookieBackedWebId()\n }\n\n if (webId) {\n this.fallbackWebId = webId\n } else {\n this.fallbackWebId = null\n }\n\n if (webId) {\n me = this.saveUser(webId)\n }\n\n if (me) {\n debug.log(`(Logged in as ${me} by authentication)`)\n }\n\n return me\n }\n\n private async probeNssCookieBackedWebId (): Promise<string | null> {\n if (typeof window === 'undefined') {\n return null\n }\n\n const { hostname, port, protocol } = window.location\n const localhostSuffix = '.localhost'\n // NSS local pods use subdomains like alice.localhost.\n if (!hostname.endsWith(localhostSuffix)) {\n return null\n }\n\n const podName = hostname.slice(0, -localhostSuffix.length)\n if (!podName || podName === 'localhost' || podName.includes('.')) {\n return null\n }\n\n try {\n // NSS returns 403 on this account page when the cookie session is valid.\n const probeResponse = await fetch('/account/password/change', {\n credentials: 'include',\n redirect: 'manual',\n cache: 'no-store'\n })\n if (probeResponse.status !== 403) {\n return null\n }\n const origin = `${protocol}//${hostname}${port ? `:${port}` : ''}`\n return `${origin}/profile/card#me`\n } catch (_error) {\n return null\n }\n }\n\n /**\n * Saves `webId` in `context.me`\n * @param webId\n * @param context\n *\n * @returns Returns the WebID, after setting it\n */\n saveUser (\n webId: NamedNode | string | null,\n context?: AuthenticationContext\n ): NamedNode | null {\n let webIdUri: string\n if (webId) {\n webIdUri = (typeof webId === 'string') ? webId : webId.uri\n const me = namedNode(webIdUri)\n if (context) {\n context.me = me\n }\n return me\n }\n return null\n }\n\n /**\n * @returns {Promise<string|null>} Resolves with WebID URI or null\n */\n webIdFromSession (\n sessionInfo?: { webId?: string, isLoggedIn?: boolean },\n sessionRoot?: { webId?: string, isLoggedIn?: boolean, isActive?: boolean }\n ): string | null {\n const webId = sessionInfo?.webId || sessionRoot?.webId\n if (!webId) {\n return null\n }\n const infoLoggedIn = sessionInfo?.isLoggedIn\n const rootLoggedIn = sessionRoot?.isLoggedIn\n const rootActive = sessionRoot?.isActive\n if (infoLoggedIn === true || rootLoggedIn === true || rootActive === true) {\n return webId\n }\n if (infoLoggedIn === false && rootLoggedIn === false && rootActive === false) {\n return null\n }\n return webId\n }\n\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"SolidAuthnLogic.cjs.js","names":[],"sources":["../../src/authn/SolidAuthnLogic.ts"],"sourcesContent":["import { namedNode, NamedNode, sym } from 'rdflib'\nimport { appContext, offlineTestID } from './authUtil'\nimport * as debug from '../util/debug'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport type { AuthenticationContext, AuthnLogic } from '../types'\n\n// Some auth clients (uvdsl worker-backed session) only settle restore() on\n// a worker message; a missing/unreachable RefreshWorker asset makes it hang\n// forever. This caps the wait so the login UI can never spin indefinitely.\nconst SESSION_RESTORE_TIMEOUT_MS = 5000\n\n/**\n * Await a session restore promise, but give up after\n * SESSION_RESTORE_TIMEOUT_MS and resolve with undefined so callers can\n * treat a stalled restore as \"no previous session\".\n */\nasync function withRestoreTimeout<T> (promise: Promise<T> | null): Promise<T | undefined> {\n if (promise === null) return undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<undefined>(resolve => {\n timer = setTimeout(() => resolve(undefined), SESSION_RESTORE_TIMEOUT_MS)\n })\n try {\n return await Promise.race([promise, timeout])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n }\n}\n\nexport class SolidAuthnLogic implements AuthnLogic {\n private session: SessionWithLegacyEvents\n private checkUserInFlight: Promise<NamedNode | null> | null = null\n private sessionRestoreHookAttached = false\n private fallbackWebId: string | null = null\n\n constructor(solidAuthSession: SessionWithLegacyEvents) {\n this.session = solidAuthSession\n }\n\n // we created authSession getter because we want to access it as authn.authSession externally\n get authSession(): SessionWithLegacyEvents { return this.session }\n\n currentUser(): NamedNode | null {\n const app = appContext()\n if (app.viewingNoAuthPage) {\n return sym(app.webId)\n }\n const sessionAny = this.session as any\n const infoWebId = sessionAny?.info?.webId\n const sessionWebId = sessionAny?.webId\n const webId = infoWebId || sessionWebId || this.fallbackWebId\n const infoLoggedIn = sessionAny?.info?.isLoggedIn\n const sessionActive = sessionAny?.isActive\n const isLoggedIn = infoLoggedIn === true || sessionActive === true ||\n ((infoLoggedIn == null && sessionActive == null) ? Boolean(webId) : false) ||\n Boolean(this.fallbackWebId)\n if (this && this.session && webId && isLoggedIn) {\n return sym(webId)\n }\n return offlineTestID() // null unless testing\n }\n\n /**\n * Retrieves currently logged in webId from either\n * defaultTestUser or SolidAuth\n * Also activates a session after login\n * @param [setUserCallback] Optional callback\n * @returns Resolves with webId uri, if no callback provided\n */\n async checkUser<T> (\n setUserCallback?: (me: NamedNode | null) => T\n ): Promise<NamedNode | T | null> {\n // Save hash for \"restorePreviousSession\"\n const preLoginRedirectHash = new URL(window.location.href).hash\n if (preLoginRedirectHash) {\n window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)\n }\n const sessionAny = this.session as any\n if (!this.sessionRestoreHookAttached && typeof sessionAny?.events?.on === 'function') {\n // Backward-compatible hook for auth clients exposing an EventEmitter-style API.\n sessionAny.events.on('sessionRestore', (url: string) => {\n debug.log(`Session restored to ${url}`)\n if (document.location.toString() !== url) history.replaceState(null, '', url)\n })\n this.sessionRestoreHookAttached = true\n }\n\n if (!this.checkUserInFlight) {\n this.checkUserInFlight = this.resolveCurrentUser()\n }\n\n const inFlight = this.checkUserInFlight\n let me: NamedNode | null\n try {\n me = await inFlight\n } finally {\n if (this.checkUserInFlight === inFlight) {\n this.checkUserInFlight = null\n }\n }\n\n return Promise.resolve(setUserCallback ? setUserCallback(me) : me)\n }\n\n private async resolveCurrentUser (): Promise<NamedNode | null> {\n const sessionAny = this.session as any\n\n /**\n * Handle a successful authentication redirect\n */\n const redirectUrl = new URL(window.location.href)\n redirectUrl.hash = ''\n if (typeof sessionAny?.handleIncomingRedirect === 'function') {\n await sessionAny.handleIncomingRedirect({\n restorePreviousSession: true,\n url: redirectUrl.href\n })\n } else {\n // uvdsl-style session (no handleIncomingRedirect): restore then handle redirect.\n //\n // The worker-backed session (WebWorkerSession) resolves restore() ONLY\n // when the SharedWorker posts a message back. If the worker asset can't\n // be fetched — local/dev servers that don't serve the RefreshWorker\n // chunk at the resolved URL, wrong MIME type, CSP, or a worker that\n // fails before `onconnect` — the promise never settles and the login\n // UI would spin forever. Race it against a timeout and treat a stall\n // as \"no previous session\" so the page can render the login button.\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (typeof sessionAny?.restore === 'function') {\n try {\n await withRestoreTimeout(sessionAny.restore())\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n // A failed restore on an inactive session just means \"no usable\n // session to restore\" — whether that's \"No session to restore.\",\n // a stale refresh token / dead client_id returning HTTP 400, or a\n // missing session database. Never let it block the login UI: log\n // and continue as logged-out so the page renders the login button.\n // Only re-throw when the session actually became active, which is\n // an unexpected refresh failure worth surfacing.\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (isNowActive && !/no session to restore/i.test(message)) {\n throw error\n }\n debug.log(`Session restore failed, continuing logged-out: ${message}`)\n }\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('sessionRestore', window.location.href)\n }\n }\n if (typeof sessionAny?.handleRedirectFromLogin === 'function') {\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n await sessionAny.handleRedirectFromLogin()\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('login')\n }\n }\n }\n\n // Check to see if a hash was stored in local storage\n const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')\n if (postLoginRedirectHash) {\n const curUrl = new URL(window.location.href)\n if (curUrl.hash !== postLoginRedirectHash) {\n if (history.pushState) {\n // debug.log('Setting window.location.has using pushState')\n history.pushState(null, document.title, postLoginRedirectHash)\n } else {\n // debug.warn('Setting window.location.has using location.hash')\n location.hash = postLoginRedirectHash\n }\n curUrl.hash = postLoginRedirectHash\n }\n // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document\n // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location\n window.localStorage.setItem('preLoginRedirectHash', '')\n }\n\n // Check to see if already logged in / have the WebID\n let me = offlineTestID()\n if (me) {\n return me\n }\n\n let webId = this.webIdFromSession(sessionAny?.info, sessionAny)\n if (!webId) {\n // NSS-specific fallback: recover WebID from NSS cookie session when client restore is empty.\n webId = await this.probeNssCookieBackedWebId()\n }\n\n if (webId) {\n this.fallbackWebId = webId\n } else {\n this.fallbackWebId = null\n }\n\n if (webId) {\n me = this.saveUser(webId)\n }\n\n if (me) {\n debug.log(`(Logged in as ${me} by authentication)`)\n }\n\n return me\n }\n\n private async probeNssCookieBackedWebId (): Promise<string | null> {\n if (typeof window === 'undefined') {\n return null\n }\n\n const { hostname, port, protocol } = window.location\n const localhostSuffix = '.localhost'\n // NSS local pods use subdomains like alice.localhost.\n if (!hostname.endsWith(localhostSuffix)) {\n return null\n }\n\n const podName = hostname.slice(0, -localhostSuffix.length)\n if (!podName || podName === 'localhost' || podName.includes('.')) {\n return null\n }\n\n try {\n // NSS returns 403 on this account page when the cookie session is valid.\n const probeResponse = await fetch('/account/password/change', {\n credentials: 'include',\n redirect: 'manual',\n cache: 'no-store'\n })\n if (probeResponse.status !== 403) {\n return null\n }\n const origin = `${protocol}//${hostname}${port ? `:${port}` : ''}`\n return `${origin}/profile/card#me`\n } catch (_error) {\n return null\n }\n }\n\n /**\n * Saves `webId` in `context.me`\n * @param webId\n * @param context\n *\n * @returns Returns the WebID, after setting it\n */\n saveUser (\n webId: NamedNode | string | null,\n context?: AuthenticationContext\n ): NamedNode | null {\n let webIdUri: string\n if (webId) {\n webIdUri = (typeof webId === 'string') ? webId : webId.uri\n const me = namedNode(webIdUri)\n if (context) {\n context.me = me\n }\n return me\n }\n return null\n }\n\n /**\n * @returns {Promise<string|null>} Resolves with WebID URI or null\n */\n webIdFromSession (\n sessionInfo?: { webId?: string, isLoggedIn?: boolean },\n sessionRoot?: { webId?: string, isLoggedIn?: boolean, isActive?: boolean }\n ): string | null {\n const webId = sessionInfo?.webId || sessionRoot?.webId\n if (!webId) {\n return null\n }\n const infoLoggedIn = sessionInfo?.isLoggedIn\n const rootLoggedIn = sessionRoot?.isLoggedIn\n const rootActive = sessionRoot?.isActive\n if (infoLoggedIn === true || rootLoggedIn === true || rootActive === true) {\n return webId\n }\n if (infoLoggedIn === false && rootLoggedIn === false && rootActive === false) {\n return null\n }\n return webId\n }\n\n}\n"],"mappings":"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"}
@@ -53,10 +53,10 @@ var s = class {
53
53
  if (typeof t?.restore == "function") {
54
54
  try {
55
55
  await o(t.restore());
56
- } catch (t) {
57
- let n = t instanceof Error ? t.message : String(t);
58
- if (!/no session to restore/i.test(n)) throw t;
59
- e("No previous session to restore");
56
+ } catch (n) {
57
+ let r = n instanceof Error ? n.message : String(n);
58
+ if ((t?.isActive ?? !!t?.webId) && !/no session to restore/i.test(r)) throw n;
59
+ e(`Session restore failed, continuing logged-out: ${r}`);
60
60
  }
61
61
  let r = t?.isActive ?? !!t?.webId;
62
62
  !n && r && t.events?.emit("sessionRestore", window.location.href);
@@ -1 +1 @@
1
- {"version":3,"file":"SolidAuthnLogic.esm.js","names":[],"sources":["../../src/authn/SolidAuthnLogic.ts"],"sourcesContent":["import { namedNode, NamedNode, sym } from 'rdflib'\nimport { appContext, offlineTestID } from './authUtil'\nimport * as debug from '../util/debug'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport type { AuthenticationContext, AuthnLogic } from '../types'\n\n// Some auth clients (uvdsl worker-backed session) only settle restore() on\n// a worker message; a missing/unreachable RefreshWorker asset makes it hang\n// forever. This caps the wait so the login UI can never spin indefinitely.\nconst SESSION_RESTORE_TIMEOUT_MS = 5000\n\n/**\n * Await a session restore promise, but give up after\n * SESSION_RESTORE_TIMEOUT_MS and resolve with undefined so callers can\n * treat a stalled restore as \"no previous session\".\n */\nasync function withRestoreTimeout<T> (promise: Promise<T> | null): Promise<T | undefined> {\n if (promise === null) return undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<undefined>(resolve => {\n timer = setTimeout(() => resolve(undefined), SESSION_RESTORE_TIMEOUT_MS)\n })\n try {\n return await Promise.race([promise, timeout])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n }\n}\n\nexport class SolidAuthnLogic implements AuthnLogic {\n private session: SessionWithLegacyEvents\n private checkUserInFlight: Promise<NamedNode | null> | null = null\n private sessionRestoreHookAttached = false\n private fallbackWebId: string | null = null\n\n constructor(solidAuthSession: SessionWithLegacyEvents) {\n this.session = solidAuthSession\n }\n\n // we created authSession getter because we want to access it as authn.authSession externally\n get authSession(): SessionWithLegacyEvents { return this.session }\n\n currentUser(): NamedNode | null {\n const app = appContext()\n if (app.viewingNoAuthPage) {\n return sym(app.webId)\n }\n const sessionAny = this.session as any\n const infoWebId = sessionAny?.info?.webId\n const sessionWebId = sessionAny?.webId\n const webId = infoWebId || sessionWebId || this.fallbackWebId\n const infoLoggedIn = sessionAny?.info?.isLoggedIn\n const sessionActive = sessionAny?.isActive\n const isLoggedIn = infoLoggedIn === true || sessionActive === true ||\n ((infoLoggedIn == null && sessionActive == null) ? Boolean(webId) : false) ||\n Boolean(this.fallbackWebId)\n if (this && this.session && webId && isLoggedIn) {\n return sym(webId)\n }\n return offlineTestID() // null unless testing\n }\n\n /**\n * Retrieves currently logged in webId from either\n * defaultTestUser or SolidAuth\n * Also activates a session after login\n * @param [setUserCallback] Optional callback\n * @returns Resolves with webId uri, if no callback provided\n */\n async checkUser<T> (\n setUserCallback?: (me: NamedNode | null) => T\n ): Promise<NamedNode | T | null> {\n // Save hash for \"restorePreviousSession\"\n const preLoginRedirectHash = new URL(window.location.href).hash\n if (preLoginRedirectHash) {\n window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)\n }\n const sessionAny = this.session as any\n if (!this.sessionRestoreHookAttached && typeof sessionAny?.events?.on === 'function') {\n // Backward-compatible hook for auth clients exposing an EventEmitter-style API.\n sessionAny.events.on('sessionRestore', (url: string) => {\n debug.log(`Session restored to ${url}`)\n if (document.location.toString() !== url) history.replaceState(null, '', url)\n })\n this.sessionRestoreHookAttached = true\n }\n\n if (!this.checkUserInFlight) {\n this.checkUserInFlight = this.resolveCurrentUser()\n }\n\n const inFlight = this.checkUserInFlight\n let me: NamedNode | null\n try {\n me = await inFlight\n } finally {\n if (this.checkUserInFlight === inFlight) {\n this.checkUserInFlight = null\n }\n }\n\n return Promise.resolve(setUserCallback ? setUserCallback(me) : me)\n }\n\n private async resolveCurrentUser (): Promise<NamedNode | null> {\n const sessionAny = this.session as any\n\n /**\n * Handle a successful authentication redirect\n */\n const redirectUrl = new URL(window.location.href)\n redirectUrl.hash = ''\n if (typeof sessionAny?.handleIncomingRedirect === 'function') {\n await sessionAny.handleIncomingRedirect({\n restorePreviousSession: true,\n url: redirectUrl.href\n })\n } else {\n // uvdsl-style session (no handleIncomingRedirect): restore then handle redirect.\n //\n // The worker-backed session (WebWorkerSession) resolves restore() ONLY\n // when the SharedWorker posts a message back. If the worker asset can't\n // be fetched — local/dev servers that don't serve the RefreshWorker\n // chunk at the resolved URL, wrong MIME type, CSP, or a worker that\n // fails before `onconnect` — the promise never settles and the login\n // UI would spin forever. Race it against a timeout and treat a stall\n // as \"no previous session\" so the page can render the login button.\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (typeof sessionAny?.restore === 'function') {\n try {\n await withRestoreTimeout(sessionAny.restore())\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n if (!/no session to restore/i.test(message)) {\n throw error\n }\n debug.log('No previous session to restore')\n }\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('sessionRestore', window.location.href)\n }\n }\n if (typeof sessionAny?.handleRedirectFromLogin === 'function') {\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n await sessionAny.handleRedirectFromLogin()\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('login')\n }\n }\n }\n\n // Check to see if a hash was stored in local storage\n const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')\n if (postLoginRedirectHash) {\n const curUrl = new URL(window.location.href)\n if (curUrl.hash !== postLoginRedirectHash) {\n if (history.pushState) {\n // debug.log('Setting window.location.has using pushState')\n history.pushState(null, document.title, postLoginRedirectHash)\n } else {\n // debug.warn('Setting window.location.has using location.hash')\n location.hash = postLoginRedirectHash\n }\n curUrl.hash = postLoginRedirectHash\n }\n // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document\n // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location\n window.localStorage.setItem('preLoginRedirectHash', '')\n }\n\n // Check to see if already logged in / have the WebID\n let me = offlineTestID()\n if (me) {\n return me\n }\n\n let webId = this.webIdFromSession(sessionAny?.info, sessionAny)\n if (!webId) {\n // NSS-specific fallback: recover WebID from NSS cookie session when client restore is empty.\n webId = await this.probeNssCookieBackedWebId()\n }\n\n if (webId) {\n this.fallbackWebId = webId\n } else {\n this.fallbackWebId = null\n }\n\n if (webId) {\n me = this.saveUser(webId)\n }\n\n if (me) {\n debug.log(`(Logged in as ${me} by authentication)`)\n }\n\n return me\n }\n\n private async probeNssCookieBackedWebId (): Promise<string | null> {\n if (typeof window === 'undefined') {\n return null\n }\n\n const { hostname, port, protocol } = window.location\n const localhostSuffix = '.localhost'\n // NSS local pods use subdomains like alice.localhost.\n if (!hostname.endsWith(localhostSuffix)) {\n return null\n }\n\n const podName = hostname.slice(0, -localhostSuffix.length)\n if (!podName || podName === 'localhost' || podName.includes('.')) {\n return null\n }\n\n try {\n // NSS returns 403 on this account page when the cookie session is valid.\n const probeResponse = await fetch('/account/password/change', {\n credentials: 'include',\n redirect: 'manual',\n cache: 'no-store'\n })\n if (probeResponse.status !== 403) {\n return null\n }\n const origin = `${protocol}//${hostname}${port ? `:${port}` : ''}`\n return `${origin}/profile/card#me`\n } catch (_error) {\n return null\n }\n }\n\n /**\n * Saves `webId` in `context.me`\n * @param webId\n * @param context\n *\n * @returns Returns the WebID, after setting it\n */\n saveUser (\n webId: NamedNode | string | null,\n context?: AuthenticationContext\n ): NamedNode | null {\n let webIdUri: string\n if (webId) {\n webIdUri = (typeof webId === 'string') ? webId : webId.uri\n const me = namedNode(webIdUri)\n if (context) {\n context.me = me\n }\n return me\n }\n return null\n }\n\n /**\n * @returns {Promise<string|null>} Resolves with WebID URI or null\n */\n webIdFromSession (\n sessionInfo?: { webId?: string, isLoggedIn?: boolean },\n sessionRoot?: { webId?: string, isLoggedIn?: boolean, isActive?: boolean }\n ): string | null {\n const webId = sessionInfo?.webId || sessionRoot?.webId\n if (!webId) {\n return null\n }\n const infoLoggedIn = sessionInfo?.isLoggedIn\n const rootLoggedIn = sessionRoot?.isLoggedIn\n const rootActive = sessionRoot?.isActive\n if (infoLoggedIn === true || rootLoggedIn === true || rootActive === true) {\n return webId\n }\n if (infoLoggedIn === false && rootLoggedIn === false && rootActive === false) {\n return null\n }\n return webId\n }\n\n}\n"],"mappings":";;;;AASA,IAAM,IAA6B;AAOnC,eAAe,EAAuB,GAAoD;CACxF,IAAI,MAAY,MAAM;CACtB,IAAI,GACE,IAAU,IAAI,SAAmB,MAAW;EAChD,IAAQ,iBAAiB,EAAQ,KAAA,CAAS,GAAG,CAA0B;CACzE,CAAC;CACD,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,GAAS,CAAO,CAAC;CAC9C,UAAU;EACR,AAAI,MAAU,KAAA,KAAW,aAAa,CAAK;CAC7C;AACF;AAEA,IAAa,IAAb,MAAmD;CAMjD,YAAY,GAA2C;EACrD,yBAL4D,wCACzB,yBACE,MAGrC,KAAK,UAAU;CACjB;CAGA,IAAI,cAAuC;EAAE,OAAO,KAAK;CAAQ;CAEjE,cAAgC;EAC9B,IAAM,IAAM,EAAW;EACvB,IAAI,EAAI,mBACN,OAAO,EAAI,EAAI,KAAK;EAEtB,IAAM,IAAa,KAAK,SAClB,IAAY,GAAY,MAAM,OAC9B,IAAe,GAAY,OAC3B,IAAQ,KAAa,KAAgB,KAAK,eAC1C,IAAe,GAAY,MAAM,YACjC,IAAgB,GAAY,UAC5B,IAAa,MAAiB,MAAQ,MAAkB,OAC1D,KAAgB,QAAQ,KAAiB,OAAQ,EAAQ,IAAS,OACpE,EAAQ,KAAK;EAIf,OAHI,QAAQ,KAAK,WAAW,KAAS,IAC5B,EAAI,CAAK,IAEX,EAAc;CACvB;CASA,MAAM,UACJ,GAC+B;EAE/B,IAAM,IAAuB,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,CAAC;EAC3D,AAAI,KACF,OAAO,aAAa,QAAQ,wBAAwB,CAAoB;EAE1E,IAAM,IAAa,KAAK;EAUxB,AATI,CAAC,KAAK,8BAA8B,OAAO,GAAY,QAAQ,MAAO,eAExE,EAAW,OAAO,GAAG,mBAAmB,MAAgB;GAEtD,AADA,EAAU,uBAAuB,GAAK,GAClC,SAAS,SAAS,SAAS,MAAM,KAAK,QAAQ,aAAa,MAAM,IAAI,CAAG;EAC9E,CAAC,GACD,KAAK,6BAA6B,KAGpC,AACE,KAAK,sBAAoB,KAAK,mBAAmB;EAGnD,IAAM,IAAW,KAAK,mBAClB;EACJ,IAAI;GACF,IAAK,MAAM;EACb,UAAU;GACR,AAAI,KAAK,sBAAsB,MAC7B,KAAK,oBAAoB;EAE7B;EAEA,OAAO,QAAQ,QAAQ,IAAkB,EAAgB,CAAE,IAAI,CAAE;CACnE;CAEA,MAAc,qBAAiD;EAC7D,IAAM,IAAa,KAAK,SAKlB,IAAc,IAAI,IAAI,OAAO,SAAS,IAAI;EAEhD,IADA,EAAY,OAAO,IACf,OAAO,GAAY,0BAA2B,YAChD,MAAM,EAAW,uBAAuB;GACtC,wBAAwB;GACxB,KAAK,EAAY;EACnB,CAAC;OACI;GAUL,IAAM,IAAY,GAAY,YAAY,EAAQ,GAAY;GAC9D,IAAI,OAAO,GAAY,WAAY,YAAY;IAC7C,IAAI;KACF,MAAM,EAAmB,EAAW,QAAQ,CAAC;IAC/C,SAAS,GAAO;KACd,IAAM,IAAU,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK;KACrE,IAAI,CAAC,yBAAyB,KAAK,CAAO,GACxC,MAAM;KAER,EAAU,gCAAgC;IAC5C;IACA,IAAM,IAAc,GAAY,YAAY,EAAQ,GAAY;IAChE,AAAI,CAAC,KAAa,KAChB,EAAW,QAAQ,KAAK,kBAAkB,OAAO,SAAS,IAAI;GAElE;GACA,IAAI,OAAO,GAAY,2BAA4B,YAAY;IAC7D,IAAM,IAAY,GAAY,YAAY,EAAQ,GAAY;IAC9D,MAAM,EAAW,wBAAwB;IACzC,IAAM,IAAc,GAAY,YAAY,EAAQ,GAAY;IAChE,AAAI,CAAC,KAAa,KAChB,EAAW,QAAQ,KAAK,OAAO;GAEnC;EACF;EAGA,IAAM,IAAwB,OAAO,aAAa,QAAQ,sBAAsB;EAChF,IAAI,GAAuB;GACzB,IAAM,IAAS,IAAI,IAAI,OAAO,SAAS,IAAI;GAa3C,AAZI,EAAO,SAAS,MACd,QAAQ,YAEV,QAAQ,UAAU,MAAM,SAAS,OAAO,CAAqB,IAG7D,SAAS,OAAO,GAElB,EAAO,OAAO,IAIhB,OAAO,aAAa,QAAQ,wBAAwB,EAAE;EACxD;EAGA,IAAI,IAAK,EAAc;EACvB,IAAI,GACF,OAAO;EAGT,IAAI,IAAQ,KAAK,iBAAiB,GAAY,MAAM,CAAU;EAoB9D,OAnBA,AAEE,MAAQ,MAAM,KAAK,0BAA0B,GAG3C,IACF,KAAK,gBAAgB,IAErB,KAAK,gBAAgB,MAGnB,MACF,IAAK,KAAK,SAAS,CAAK,IAGtB,KACF,EAAU,iBAAiB,EAAG,oBAAoB,GAG7C;CACT;CAEA,MAAc,4BAAqD;EACjE,IAAI,OAAO,SAAW,KACpB,OAAO;EAGT,IAAM,EAAE,aAAU,SAAM,gBAAa,OAAO;EAG5C,IAAI,CAAC,EAAS,SAAS,YAAe,GACpC,OAAO;EAGT,IAAM,IAAU,EAAS,MAAM,GAAG,GAAuB;EACzD,IAAI,CAAC,KAAW,MAAY,eAAe,EAAQ,SAAS,GAAG,GAC7D,OAAO;EAGT,IAAI;GAWF,QAJI,MALwB,MAAM,4BAA4B;IAC5D,aAAa;IACb,UAAU;IACV,OAAO;GACT,CAAC,EAAA,CACiB,WAAW,MAItB,GAAG,GADQ,EAAS,IAAI,IAAW,IAAO,IAAI,MAAS,KAC7C,oBAHR;EAIX,QAAiB;GACf,OAAO;EACT;CACF;CASA,SACE,GACA,GACkB;EAClB,IAAI;EACJ,IAAI,GAAO;GACT,IAAY,OAAO,KAAU,WAAY,IAAQ,EAAM;GACvD,IAAM,IAAK,EAAU,CAAQ;GAI7B,OAHI,MACF,EAAQ,KAAK,IAER;EACT;EACA,OAAO;CACT;CAKA,iBACE,GACA,GACe;EACf,IAAM,IAAQ,GAAa,SAAS,GAAa;EACjD,IAAI,CAAC,GACH,OAAO;EAET,IAAM,IAAe,GAAa,YAC5B,IAAe,GAAa,YAC5B,IAAa,GAAa;EAOhC,OANI,MAAiB,MAAQ,MAAiB,MAAQ,MAAe,KAC5D,IAEL,MAAiB,MAAS,MAAiB,MAAS,MAAe,KAC9D,OAEF;CACT;AAEF"}
1
+ {"version":3,"file":"SolidAuthnLogic.esm.js","names":[],"sources":["../../src/authn/SolidAuthnLogic.ts"],"sourcesContent":["import { namedNode, NamedNode, sym } from 'rdflib'\nimport { appContext, offlineTestID } from './authUtil'\nimport * as debug from '../util/debug'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport type { AuthenticationContext, AuthnLogic } from '../types'\n\n// Some auth clients (uvdsl worker-backed session) only settle restore() on\n// a worker message; a missing/unreachable RefreshWorker asset makes it hang\n// forever. This caps the wait so the login UI can never spin indefinitely.\nconst SESSION_RESTORE_TIMEOUT_MS = 5000\n\n/**\n * Await a session restore promise, but give up after\n * SESSION_RESTORE_TIMEOUT_MS and resolve with undefined so callers can\n * treat a stalled restore as \"no previous session\".\n */\nasync function withRestoreTimeout<T> (promise: Promise<T> | null): Promise<T | undefined> {\n if (promise === null) return undefined\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<undefined>(resolve => {\n timer = setTimeout(() => resolve(undefined), SESSION_RESTORE_TIMEOUT_MS)\n })\n try {\n return await Promise.race([promise, timeout])\n } finally {\n if (timer !== undefined) clearTimeout(timer)\n }\n}\n\nexport class SolidAuthnLogic implements AuthnLogic {\n private session: SessionWithLegacyEvents\n private checkUserInFlight: Promise<NamedNode | null> | null = null\n private sessionRestoreHookAttached = false\n private fallbackWebId: string | null = null\n\n constructor(solidAuthSession: SessionWithLegacyEvents) {\n this.session = solidAuthSession\n }\n\n // we created authSession getter because we want to access it as authn.authSession externally\n get authSession(): SessionWithLegacyEvents { return this.session }\n\n currentUser(): NamedNode | null {\n const app = appContext()\n if (app.viewingNoAuthPage) {\n return sym(app.webId)\n }\n const sessionAny = this.session as any\n const infoWebId = sessionAny?.info?.webId\n const sessionWebId = sessionAny?.webId\n const webId = infoWebId || sessionWebId || this.fallbackWebId\n const infoLoggedIn = sessionAny?.info?.isLoggedIn\n const sessionActive = sessionAny?.isActive\n const isLoggedIn = infoLoggedIn === true || sessionActive === true ||\n ((infoLoggedIn == null && sessionActive == null) ? Boolean(webId) : false) ||\n Boolean(this.fallbackWebId)\n if (this && this.session && webId && isLoggedIn) {\n return sym(webId)\n }\n return offlineTestID() // null unless testing\n }\n\n /**\n * Retrieves currently logged in webId from either\n * defaultTestUser or SolidAuth\n * Also activates a session after login\n * @param [setUserCallback] Optional callback\n * @returns Resolves with webId uri, if no callback provided\n */\n async checkUser<T> (\n setUserCallback?: (me: NamedNode | null) => T\n ): Promise<NamedNode | T | null> {\n // Save hash for \"restorePreviousSession\"\n const preLoginRedirectHash = new URL(window.location.href).hash\n if (preLoginRedirectHash) {\n window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)\n }\n const sessionAny = this.session as any\n if (!this.sessionRestoreHookAttached && typeof sessionAny?.events?.on === 'function') {\n // Backward-compatible hook for auth clients exposing an EventEmitter-style API.\n sessionAny.events.on('sessionRestore', (url: string) => {\n debug.log(`Session restored to ${url}`)\n if (document.location.toString() !== url) history.replaceState(null, '', url)\n })\n this.sessionRestoreHookAttached = true\n }\n\n if (!this.checkUserInFlight) {\n this.checkUserInFlight = this.resolveCurrentUser()\n }\n\n const inFlight = this.checkUserInFlight\n let me: NamedNode | null\n try {\n me = await inFlight\n } finally {\n if (this.checkUserInFlight === inFlight) {\n this.checkUserInFlight = null\n }\n }\n\n return Promise.resolve(setUserCallback ? setUserCallback(me) : me)\n }\n\n private async resolveCurrentUser (): Promise<NamedNode | null> {\n const sessionAny = this.session as any\n\n /**\n * Handle a successful authentication redirect\n */\n const redirectUrl = new URL(window.location.href)\n redirectUrl.hash = ''\n if (typeof sessionAny?.handleIncomingRedirect === 'function') {\n await sessionAny.handleIncomingRedirect({\n restorePreviousSession: true,\n url: redirectUrl.href\n })\n } else {\n // uvdsl-style session (no handleIncomingRedirect): restore then handle redirect.\n //\n // The worker-backed session (WebWorkerSession) resolves restore() ONLY\n // when the SharedWorker posts a message back. If the worker asset can't\n // be fetched — local/dev servers that don't serve the RefreshWorker\n // chunk at the resolved URL, wrong MIME type, CSP, or a worker that\n // fails before `onconnect` — the promise never settles and the login\n // UI would spin forever. Race it against a timeout and treat a stall\n // as \"no previous session\" so the page can render the login button.\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (typeof sessionAny?.restore === 'function') {\n try {\n await withRestoreTimeout(sessionAny.restore())\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n // A failed restore on an inactive session just means \"no usable\n // session to restore\" — whether that's \"No session to restore.\",\n // a stale refresh token / dead client_id returning HTTP 400, or a\n // missing session database. Never let it block the login UI: log\n // and continue as logged-out so the page renders the login button.\n // Only re-throw when the session actually became active, which is\n // an unexpected refresh failure worth surfacing.\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (isNowActive && !/no session to restore/i.test(message)) {\n throw error\n }\n debug.log(`Session restore failed, continuing logged-out: ${message}`)\n }\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('sessionRestore', window.location.href)\n }\n }\n if (typeof sessionAny?.handleRedirectFromLogin === 'function') {\n const wasActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n await sessionAny.handleRedirectFromLogin()\n const isNowActive = sessionAny?.isActive ?? Boolean(sessionAny?.webId)\n if (!wasActive && isNowActive) {\n sessionAny.events?.emit('login')\n }\n }\n }\n\n // Check to see if a hash was stored in local storage\n const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')\n if (postLoginRedirectHash) {\n const curUrl = new URL(window.location.href)\n if (curUrl.hash !== postLoginRedirectHash) {\n if (history.pushState) {\n // debug.log('Setting window.location.has using pushState')\n history.pushState(null, document.title, postLoginRedirectHash)\n } else {\n // debug.warn('Setting window.location.has using location.hash')\n location.hash = postLoginRedirectHash\n }\n curUrl.hash = postLoginRedirectHash\n }\n // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document\n // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location\n window.localStorage.setItem('preLoginRedirectHash', '')\n }\n\n // Check to see if already logged in / have the WebID\n let me = offlineTestID()\n if (me) {\n return me\n }\n\n let webId = this.webIdFromSession(sessionAny?.info, sessionAny)\n if (!webId) {\n // NSS-specific fallback: recover WebID from NSS cookie session when client restore is empty.\n webId = await this.probeNssCookieBackedWebId()\n }\n\n if (webId) {\n this.fallbackWebId = webId\n } else {\n this.fallbackWebId = null\n }\n\n if (webId) {\n me = this.saveUser(webId)\n }\n\n if (me) {\n debug.log(`(Logged in as ${me} by authentication)`)\n }\n\n return me\n }\n\n private async probeNssCookieBackedWebId (): Promise<string | null> {\n if (typeof window === 'undefined') {\n return null\n }\n\n const { hostname, port, protocol } = window.location\n const localhostSuffix = '.localhost'\n // NSS local pods use subdomains like alice.localhost.\n if (!hostname.endsWith(localhostSuffix)) {\n return null\n }\n\n const podName = hostname.slice(0, -localhostSuffix.length)\n if (!podName || podName === 'localhost' || podName.includes('.')) {\n return null\n }\n\n try {\n // NSS returns 403 on this account page when the cookie session is valid.\n const probeResponse = await fetch('/account/password/change', {\n credentials: 'include',\n redirect: 'manual',\n cache: 'no-store'\n })\n if (probeResponse.status !== 403) {\n return null\n }\n const origin = `${protocol}//${hostname}${port ? `:${port}` : ''}`\n return `${origin}/profile/card#me`\n } catch (_error) {\n return null\n }\n }\n\n /**\n * Saves `webId` in `context.me`\n * @param webId\n * @param context\n *\n * @returns Returns the WebID, after setting it\n */\n saveUser (\n webId: NamedNode | string | null,\n context?: AuthenticationContext\n ): NamedNode | null {\n let webIdUri: string\n if (webId) {\n webIdUri = (typeof webId === 'string') ? webId : webId.uri\n const me = namedNode(webIdUri)\n if (context) {\n context.me = me\n }\n return me\n }\n return null\n }\n\n /**\n * @returns {Promise<string|null>} Resolves with WebID URI or null\n */\n webIdFromSession (\n sessionInfo?: { webId?: string, isLoggedIn?: boolean },\n sessionRoot?: { webId?: string, isLoggedIn?: boolean, isActive?: boolean }\n ): string | null {\n const webId = sessionInfo?.webId || sessionRoot?.webId\n if (!webId) {\n return null\n }\n const infoLoggedIn = sessionInfo?.isLoggedIn\n const rootLoggedIn = sessionRoot?.isLoggedIn\n const rootActive = sessionRoot?.isActive\n if (infoLoggedIn === true || rootLoggedIn === true || rootActive === true) {\n return webId\n }\n if (infoLoggedIn === false && rootLoggedIn === false && rootActive === false) {\n return null\n }\n return webId\n }\n\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../_virtual/_rolldown/runtime.cjs.js"),t=require("../util/debug.cjs.js"),n=require("../acl/aclLogic.cjs.js"),r=require("../authn/SolidAuthnLogic.cjs.js"),i=require("../chat/chatLogic.cjs.js"),a=require("../inbox/inboxLogic.cjs.js"),o=require("../util/containerLogic.cjs.js"),s=require("../profile/profileLogic.cjs.js"),c=require("../typeIndex/typeIndexLogic.cjs.js"),l=require("../util/utilityLogic.cjs.js");let u=require("rdflib");u=e.__toESM(u);function d(e,d){t.log(`SolidLogic: Unique instance created. There should only be one of these.`);let f=u.graph();u.fetcher(f,{fetch:e.fetch}),f.updater=new u.UpdateManager(f),f.features=[];let p=new r.SolidAuthnLogic(d),m=n.createAclLogic(f),h=o.createContainerLogic(f),g=l.createUtilityLogic(f,m,h),_=s.createProfileLogic(f,p,g),v=i.createChatLogic(f,_),y=a.createInboxLogic(f,_,g,h,m),b=c.createTypeIndexLogic(f,p,_,g);t.log(`SolidAuthnLogic initialized`);function x(e){return f.fetcher.load(e)}function S(e,t=[]){return new Promise((n,r)=>{f.updater.update(e,t,function(e,t,i){t?n():r(Error(i))})})}function C(){f.statements.slice().forEach(f.remove.bind(f))}return{store:f,authn:p,acl:m,inbox:y,chat:v,profile:_,typeIndex:b,load:x,updatePromise:S,clearStore:C}}exports.createSolidLogic=d;
1
+ const e=require("../_virtual/_rolldown/runtime.cjs.js"),t=require("../util/debug.cjs.js"),n=require("../acl/aclLogic.cjs.js"),r=require("../authn/SolidAuthnLogic.cjs.js"),i=require("../chat/chatLogic.cjs.js"),a=require("../inbox/inboxLogic.cjs.js"),o=require("../resource/resourceLogic.cjs.js"),s=require("../util/containerLogic.cjs.js"),c=require("../profile/profileLogic.cjs.js"),l=require("../typeIndex/typeIndexLogic.cjs.js"),u=require("../util/utilityLogic.cjs.js");let d=require("rdflib");d=e.__toESM(d);function f(e,f){t.log(`SolidLogic: Unique instance created. There should only be one of these.`);let p=d.graph();d.fetcher(p,{fetch:e.fetch}),p.updater=new d.UpdateManager(p),p.features=[];let m=new r.SolidAuthnLogic(f),h=n.createAclLogic(p),g=s.createContainerLogic(p),_=u.createUtilityLogic(p,h,g),v=c.createProfileLogic(p,m,_),y=i.createChatLogic(p,v),b=a.createInboxLogic(p,v,_,g,h),x=l.createTypeIndexLogic(p,m,v,_),S=o.createResourceLogic(p,h,g,x);t.log(`SolidAuthnLogic initialized`);function C(e){return p.fetcher.load(e)}function w(e,t=[]){return new Promise((n,r)=>{p.updater.update(e,t,function(e,t,i){t?n():r(Error(i))})})}function T(){p.statements.slice().forEach(p.remove.bind(p))}return{store:p,authn:m,acl:h,resource:S,inbox:b,chat:y,profile:v,typeIndex:x,load:C,updatePromise:w,clearStore:T}}exports.createSolidLogic=f;
2
2
  //# sourceMappingURL=solidLogic.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"solidLogic.cjs.js","names":[],"sources":["../../src/logic/solidLogic.ts"],"sourcesContent":["import * as rdf from 'rdflib'\nimport { LiveStore, NamedNode, Statement } from 'rdflib'\nimport { createAclLogic } from '../acl/aclLogic'\nimport { SolidAuthnLogic } from '../authn/SolidAuthnLogic'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport { createChatLogic } from '../chat/chatLogic'\nimport { createInboxLogic } from '../inbox/inboxLogic'\nimport { createProfileLogic } from '../profile/profileLogic'\nimport { createTypeIndexLogic } from '../typeIndex/typeIndexLogic'\nimport { createContainerLogic } from '../util/containerLogic'\nimport { createUtilityLogic } from '../util/utilityLogic'\nimport type { AuthnLogic, SolidLogic } from '../types'\nimport * as debug from '../util/debug'\n/*\n** It is important to distinquish `fetch`, a function provided by the browser\n** and `Fetcher`, a helper object for the rdflib Store which turns it\n** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is\n** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,\n*/\nexport function createSolidLogic(specialFetch: { fetch: (url: any, requestInit: any) => any }, session: SessionWithLegacyEvents): SolidLogic {\n\n debug.log('SolidLogic: Unique instance created. There should only be one of these.')\n const store: LiveStore = rdf.graph() as LiveStore\n rdf.fetcher(store, {fetch: specialFetch.fetch}) // Attach a web I/O module, store.fetcher\n store.updater = new rdf.UpdateManager(store) // Add real-time live updates store.updater\n store.features = [] // disable automatic node merging on store load\n\n const authn: AuthnLogic = new SolidAuthnLogic(session)\n \n const acl = createAclLogic(store)\n const containerLogic = createContainerLogic(store)\n const utilityLogic = createUtilityLogic(store, acl, containerLogic)\n const profile = createProfileLogic(store, authn, utilityLogic)\n const chat = createChatLogic(store, profile)\n const inbox = createInboxLogic(store, profile, utilityLogic, containerLogic, acl)\n const typeIndex = createTypeIndexLogic(store, authn, profile, utilityLogic)\n debug.log('SolidAuthnLogic initialized')\n\n function load(doc: NamedNode | NamedNode[] | string) {\n return store.fetcher.load(doc)\n }\n\n // @@@@ use the one in rdflib.js when it is available and delete this\n function updatePromise(\n del: Array<Statement>,\n ins: Array<Statement> = []\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n store.updater.update(del, ins, function (_uri, ok, errorBody) {\n if (!ok) {\n reject(new Error(errorBody))\n } else {\n resolve()\n }\n }) // callback\n }) // promise\n }\n\n function clearStore() {\n store.statements.slice().forEach(store.remove.bind(store))\n }\n\n return {\n store,\n authn,\n acl,\n inbox,\n chat,\n profile,\n typeIndex,\n load,\n updatePromise,\n clearStore\n }\n}\n"],"mappings":"gdAmBA,SAAgB,EAAiB,EAA8D,EAA8C,CAEzI,EAAA,IAAU,0EAA0E,EACpF,IAAM,EAAmB,EAAI,MAAM,EACnC,EAAI,QAAQ,EAAO,CAAC,MAAO,EAAa,KAAK,CAAC,EAC9C,EAAM,QAAU,IAAI,EAAI,cAAc,CAAK,EAC3C,EAAM,SAAW,CAAC,EAElB,IAAM,EAAoB,IAAI,EAAA,gBAAgB,CAAO,EAE/C,EAAM,EAAA,eAAe,CAAK,EAC1B,EAAiB,EAAA,qBAAqB,CAAK,EAC3C,EAAe,EAAA,mBAAmB,EAAO,EAAK,CAAc,EAC5D,EAAU,EAAA,mBAAmB,EAAO,EAAO,CAAY,EACvD,EAAO,EAAA,gBAAgB,EAAO,CAAO,EACrC,EAAQ,EAAA,iBAAiB,EAAO,EAAS,EAAc,EAAgB,CAAG,EAC1E,EAAY,EAAA,qBAAqB,EAAO,EAAO,EAAS,CAAY,EAC1E,EAAA,IAAU,6BAA6B,EAEvC,SAAS,EAAK,EAAuC,CACjD,OAAO,EAAM,QAAQ,KAAK,CAAG,CACjC,CAGA,SAAS,EACL,EACA,EAAwB,CAAC,EACZ,CACb,OAAO,IAAI,SAAS,EAAS,IAAW,CACxC,EAAM,QAAQ,OAAO,EAAK,EAAK,SAAU,EAAM,EAAI,EAAW,CACrD,EAGL,EAAQ,EAFR,EAAW,MAAM,CAAS,CAAC,CAI/B,CAAC,CACD,CAAC,CACL,CAEA,SAAS,GAAa,CAClB,EAAM,WAAW,MAAM,CAAC,CAAC,QAAQ,EAAM,OAAO,KAAK,CAAK,CAAC,CAC7D,CAEA,MAAO,CACH,QACA,QACA,MACA,QACA,OACA,UACA,YACA,OACA,gBACA,YACJ,CACJ"}
1
+ {"version":3,"file":"solidLogic.cjs.js","names":[],"sources":["../../src/logic/solidLogic.ts"],"sourcesContent":["import * as rdf from 'rdflib'\nimport { LiveStore, NamedNode, Statement } from 'rdflib'\nimport { createAclLogic } from '../acl/aclLogic'\nimport { SolidAuthnLogic } from '../authn/SolidAuthnLogic'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport { createChatLogic } from '../chat/chatLogic'\nimport { createInboxLogic } from '../inbox/inboxLogic'\nimport { createResourceLogic } from '../resource/resourceLogic'\nimport { createProfileLogic } from '../profile/profileLogic'\nimport { createTypeIndexLogic } from '../typeIndex/typeIndexLogic'\nimport { createContainerLogic } from '../util/containerLogic'\nimport { createUtilityLogic } from '../util/utilityLogic'\nimport type { AuthnLogic, SolidLogic } from '../types'\nimport * as debug from '../util/debug'\n/*\n** It is important to distinquish `fetch`, a function provided by the browser\n** and `Fetcher`, a helper object for the rdflib Store which turns it\n** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is\n** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,\n*/\nexport function createSolidLogic(specialFetch: { fetch: (url: any, requestInit: any) => any }, session: SessionWithLegacyEvents): SolidLogic {\n\n debug.log('SolidLogic: Unique instance created. There should only be one of these.')\n const store: LiveStore = rdf.graph() as LiveStore\n rdf.fetcher(store, {fetch: specialFetch.fetch}) // Attach a web I/O module, store.fetcher\n store.updater = new rdf.UpdateManager(store) // Add real-time live updates store.updater\n store.features = [] // disable automatic node merging on store load\n\n const authn: AuthnLogic = new SolidAuthnLogic(session)\n \n const acl = createAclLogic(store)\n const containerLogic = createContainerLogic(store)\n const utilityLogic = createUtilityLogic(store, acl, containerLogic)\n const profile = createProfileLogic(store, authn, utilityLogic)\n const chat = createChatLogic(store, profile)\n const inbox = createInboxLogic(store, profile, utilityLogic, containerLogic, acl)\n const typeIndex = createTypeIndexLogic(store, authn, profile, utilityLogic)\n const resource = createResourceLogic(store, acl, containerLogic, typeIndex)\n debug.log('SolidAuthnLogic initialized')\n\n function load(doc: NamedNode | NamedNode[] | string) {\n return store.fetcher.load(doc)\n }\n\n // @@@@ use the one in rdflib.js when it is available and delete this\n function updatePromise(\n del: Array<Statement>,\n ins: Array<Statement> = []\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n store.updater.update(del, ins, function (_uri, ok, errorBody) {\n if (!ok) {\n reject(new Error(errorBody))\n } else {\n resolve()\n }\n }) // callback\n }) // promise\n }\n\n function clearStore() {\n store.statements.slice().forEach(store.remove.bind(store))\n }\n\n return {\n store,\n authn,\n acl,\n resource,\n inbox,\n chat,\n profile,\n typeIndex,\n load,\n updatePromise,\n clearStore\n }\n}\n"],"mappings":"8fAoBA,SAAgB,EAAiB,EAA8D,EAA8C,CAEzI,EAAA,IAAU,0EAA0E,EACpF,IAAM,EAAmB,EAAI,MAAM,EACnC,EAAI,QAAQ,EAAO,CAAC,MAAO,EAAa,KAAK,CAAC,EAC9C,EAAM,QAAU,IAAI,EAAI,cAAc,CAAK,EAC3C,EAAM,SAAW,CAAC,EAElB,IAAM,EAAoB,IAAI,EAAA,gBAAgB,CAAO,EAE/C,EAAM,EAAA,eAAe,CAAK,EAC1B,EAAiB,EAAA,qBAAqB,CAAK,EAC3C,EAAe,EAAA,mBAAmB,EAAO,EAAK,CAAc,EAC5D,EAAU,EAAA,mBAAmB,EAAO,EAAO,CAAY,EACvD,EAAO,EAAA,gBAAgB,EAAO,CAAO,EACrC,EAAQ,EAAA,iBAAiB,EAAO,EAAS,EAAc,EAAgB,CAAG,EAC1E,EAAY,EAAA,qBAAqB,EAAO,EAAO,EAAS,CAAY,EACpE,EAAW,EAAA,oBAAoB,EAAO,EAAK,EAAgB,CAAS,EAC1E,EAAA,IAAU,6BAA6B,EAEvC,SAAS,EAAK,EAAuC,CACjD,OAAO,EAAM,QAAQ,KAAK,CAAG,CACjC,CAGA,SAAS,EACL,EACA,EAAwB,CAAC,EACZ,CACb,OAAO,IAAI,SAAS,EAAS,IAAW,CACxC,EAAM,QAAQ,OAAO,EAAK,EAAK,SAAU,EAAM,EAAI,EAAW,CACrD,EAGL,EAAQ,EAFR,EAAW,MAAM,CAAS,CAAC,CAI/B,CAAC,CACD,CAAC,CACL,CAEA,SAAS,GAAa,CAClB,EAAM,WAAW,MAAM,CAAC,CAAC,QAAQ,EAAM,OAAO,KAAK,CAAK,CAAC,CAC7D,CAEA,MAAO,CACH,QACA,QACA,MACA,WACA,QACA,OACA,UACA,YACA,OACA,gBACA,YACJ,CACJ"}
@@ -3,45 +3,47 @@ import { createAclLogic as t } from "../acl/aclLogic.esm.js";
3
3
  import { SolidAuthnLogic as n } from "../authn/SolidAuthnLogic.esm.js";
4
4
  import { createChatLogic as r } from "../chat/chatLogic.esm.js";
5
5
  import { createInboxLogic as i } from "../inbox/inboxLogic.esm.js";
6
- import { createContainerLogic as a } from "../util/containerLogic.esm.js";
7
- import { createProfileLogic as o } from "../profile/profileLogic.esm.js";
8
- import { createTypeIndexLogic as s } from "../typeIndex/typeIndexLogic.esm.js";
9
- import { createUtilityLogic as c } from "../util/utilityLogic.esm.js";
10
- import * as l from "rdflib";
6
+ import { createResourceLogic as a } from "../resource/resourceLogic.esm.js";
7
+ import { createContainerLogic as o } from "../util/containerLogic.esm.js";
8
+ import { createProfileLogic as s } from "../profile/profileLogic.esm.js";
9
+ import { createTypeIndexLogic as c } from "../typeIndex/typeIndexLogic.esm.js";
10
+ import { createUtilityLogic as l } from "../util/utilityLogic.esm.js";
11
+ import * as u from "rdflib";
11
12
  //#region src/logic/solidLogic.ts
12
- function u(u, d) {
13
+ function d(d, f) {
13
14
  e("SolidLogic: Unique instance created. There should only be one of these.");
14
- let f = l.graph();
15
- l.fetcher(f, { fetch: u.fetch }), f.updater = new l.UpdateManager(f), f.features = [];
16
- let p = new n(d), m = t(f), h = a(f), g = c(f, m, h), _ = o(f, p, g), v = r(f, _), y = i(f, _, g, h, m), b = s(f, p, _, g);
15
+ let p = u.graph();
16
+ u.fetcher(p, { fetch: d.fetch }), p.updater = new u.UpdateManager(p), p.features = [];
17
+ let m = new n(f), h = t(p), g = o(p), _ = l(p, h, g), v = s(p, m, _), y = r(p, v), b = i(p, v, _, g, h), x = c(p, m, v, _), S = a(p, h, g, x);
17
18
  e("SolidAuthnLogic initialized");
18
- function x(e) {
19
- return f.fetcher.load(e);
19
+ function C(e) {
20
+ return p.fetcher.load(e);
20
21
  }
21
- function S(e, t = []) {
22
+ function w(e, t = []) {
22
23
  return new Promise((n, r) => {
23
- f.updater.update(e, t, function(e, t, i) {
24
+ p.updater.update(e, t, function(e, t, i) {
24
25
  t ? n() : r(Error(i));
25
26
  });
26
27
  });
27
28
  }
28
- function C() {
29
- f.statements.slice().forEach(f.remove.bind(f));
29
+ function T() {
30
+ p.statements.slice().forEach(p.remove.bind(p));
30
31
  }
31
32
  return {
32
- store: f,
33
- authn: p,
34
- acl: m,
35
- inbox: y,
36
- chat: v,
37
- profile: _,
38
- typeIndex: b,
39
- load: x,
40
- updatePromise: S,
41
- clearStore: C
33
+ store: p,
34
+ authn: m,
35
+ acl: h,
36
+ resource: S,
37
+ inbox: b,
38
+ chat: y,
39
+ profile: v,
40
+ typeIndex: x,
41
+ load: C,
42
+ updatePromise: w,
43
+ clearStore: T
42
44
  };
43
45
  }
44
46
  //#endregion
45
- export { u as createSolidLogic };
47
+ export { d as createSolidLogic };
46
48
 
47
49
  //# sourceMappingURL=solidLogic.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"solidLogic.esm.js","names":[],"sources":["../../src/logic/solidLogic.ts"],"sourcesContent":["import * as rdf from 'rdflib'\nimport { LiveStore, NamedNode, Statement } from 'rdflib'\nimport { createAclLogic } from '../acl/aclLogic'\nimport { SolidAuthnLogic } from '../authn/SolidAuthnLogic'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport { createChatLogic } from '../chat/chatLogic'\nimport { createInboxLogic } from '../inbox/inboxLogic'\nimport { createProfileLogic } from '../profile/profileLogic'\nimport { createTypeIndexLogic } from '../typeIndex/typeIndexLogic'\nimport { createContainerLogic } from '../util/containerLogic'\nimport { createUtilityLogic } from '../util/utilityLogic'\nimport type { AuthnLogic, SolidLogic } from '../types'\nimport * as debug from '../util/debug'\n/*\n** It is important to distinquish `fetch`, a function provided by the browser\n** and `Fetcher`, a helper object for the rdflib Store which turns it\n** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is\n** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,\n*/\nexport function createSolidLogic(specialFetch: { fetch: (url: any, requestInit: any) => any }, session: SessionWithLegacyEvents): SolidLogic {\n\n debug.log('SolidLogic: Unique instance created. There should only be one of these.')\n const store: LiveStore = rdf.graph() as LiveStore\n rdf.fetcher(store, {fetch: specialFetch.fetch}) // Attach a web I/O module, store.fetcher\n store.updater = new rdf.UpdateManager(store) // Add real-time live updates store.updater\n store.features = [] // disable automatic node merging on store load\n\n const authn: AuthnLogic = new SolidAuthnLogic(session)\n \n const acl = createAclLogic(store)\n const containerLogic = createContainerLogic(store)\n const utilityLogic = createUtilityLogic(store, acl, containerLogic)\n const profile = createProfileLogic(store, authn, utilityLogic)\n const chat = createChatLogic(store, profile)\n const inbox = createInboxLogic(store, profile, utilityLogic, containerLogic, acl)\n const typeIndex = createTypeIndexLogic(store, authn, profile, utilityLogic)\n debug.log('SolidAuthnLogic initialized')\n\n function load(doc: NamedNode | NamedNode[] | string) {\n return store.fetcher.load(doc)\n }\n\n // @@@@ use the one in rdflib.js when it is available and delete this\n function updatePromise(\n del: Array<Statement>,\n ins: Array<Statement> = []\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n store.updater.update(del, ins, function (_uri, ok, errorBody) {\n if (!ok) {\n reject(new Error(errorBody))\n } else {\n resolve()\n }\n }) // callback\n }) // promise\n }\n\n function clearStore() {\n store.statements.slice().forEach(store.remove.bind(store))\n }\n\n return {\n store,\n authn,\n acl,\n inbox,\n chat,\n profile,\n typeIndex,\n load,\n updatePromise,\n clearStore\n }\n}\n"],"mappings":";;;;;;;;;;;AAmBA,SAAgB,EAAiB,GAA8D,GAA8C;CAEzI,EAAU,0EAA0E;CACpF,IAAM,IAAmB,EAAI,MAAM;CAGnC,AAFA,EAAI,QAAQ,GAAO,EAAC,OAAO,EAAa,MAAK,CAAC,GAC9C,EAAM,UAAU,IAAI,EAAI,cAAc,CAAK,GAC3C,EAAM,WAAW,CAAC;CAElB,IAAM,IAAoB,IAAI,EAAgB,CAAO,GAE/C,IAAM,EAAe,CAAK,GAC1B,IAAiB,EAAqB,CAAK,GAC3C,IAAe,EAAmB,GAAO,GAAK,CAAc,GAC5D,IAAU,EAAmB,GAAO,GAAO,CAAY,GACvD,IAAO,EAAgB,GAAO,CAAO,GACrC,IAAQ,EAAiB,GAAO,GAAS,GAAc,GAAgB,CAAG,GAC1E,IAAY,EAAqB,GAAO,GAAO,GAAS,CAAY;CAC1E,EAAU,6BAA6B;CAEvC,SAAS,EAAK,GAAuC;EACjD,OAAO,EAAM,QAAQ,KAAK,CAAG;CACjC;CAGA,SAAS,EACL,GACA,IAAwB,CAAC,GACZ;EACb,OAAO,IAAI,SAAS,GAAS,MAAW;GACxC,EAAM,QAAQ,OAAO,GAAK,GAAK,SAAU,GAAM,GAAI,GAAW;IAC1D,AAAK,IAGL,EAAQ,IAFR,EAAW,MAAM,CAAS,CAAC;GAI/B,CAAC;EACD,CAAC;CACL;CAEA,SAAS,IAAa;EAClB,EAAM,WAAW,MAAM,CAAC,CAAC,QAAQ,EAAM,OAAO,KAAK,CAAK,CAAC;CAC7D;CAEA,OAAO;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ;AACJ"}
1
+ {"version":3,"file":"solidLogic.esm.js","names":[],"sources":["../../src/logic/solidLogic.ts"],"sourcesContent":["import * as rdf from 'rdflib'\nimport { LiveStore, NamedNode, Statement } from 'rdflib'\nimport { createAclLogic } from '../acl/aclLogic'\nimport { SolidAuthnLogic } from '../authn/SolidAuthnLogic'\nimport type { SessionWithLegacyEvents } from '../authSession/authSession'\nimport { createChatLogic } from '../chat/chatLogic'\nimport { createInboxLogic } from '../inbox/inboxLogic'\nimport { createResourceLogic } from '../resource/resourceLogic'\nimport { createProfileLogic } from '../profile/profileLogic'\nimport { createTypeIndexLogic } from '../typeIndex/typeIndexLogic'\nimport { createContainerLogic } from '../util/containerLogic'\nimport { createUtilityLogic } from '../util/utilityLogic'\nimport type { AuthnLogic, SolidLogic } from '../types'\nimport * as debug from '../util/debug'\n/*\n** It is important to distinquish `fetch`, a function provided by the browser\n** and `Fetcher`, a helper object for the rdflib Store which turns it\n** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is\n** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,\n*/\nexport function createSolidLogic(specialFetch: { fetch: (url: any, requestInit: any) => any }, session: SessionWithLegacyEvents): SolidLogic {\n\n debug.log('SolidLogic: Unique instance created. There should only be one of these.')\n const store: LiveStore = rdf.graph() as LiveStore\n rdf.fetcher(store, {fetch: specialFetch.fetch}) // Attach a web I/O module, store.fetcher\n store.updater = new rdf.UpdateManager(store) // Add real-time live updates store.updater\n store.features = [] // disable automatic node merging on store load\n\n const authn: AuthnLogic = new SolidAuthnLogic(session)\n \n const acl = createAclLogic(store)\n const containerLogic = createContainerLogic(store)\n const utilityLogic = createUtilityLogic(store, acl, containerLogic)\n const profile = createProfileLogic(store, authn, utilityLogic)\n const chat = createChatLogic(store, profile)\n const inbox = createInboxLogic(store, profile, utilityLogic, containerLogic, acl)\n const typeIndex = createTypeIndexLogic(store, authn, profile, utilityLogic)\n const resource = createResourceLogic(store, acl, containerLogic, typeIndex)\n debug.log('SolidAuthnLogic initialized')\n\n function load(doc: NamedNode | NamedNode[] | string) {\n return store.fetcher.load(doc)\n }\n\n // @@@@ use the one in rdflib.js when it is available and delete this\n function updatePromise(\n del: Array<Statement>,\n ins: Array<Statement> = []\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n store.updater.update(del, ins, function (_uri, ok, errorBody) {\n if (!ok) {\n reject(new Error(errorBody))\n } else {\n resolve()\n }\n }) // callback\n }) // promise\n }\n\n function clearStore() {\n store.statements.slice().forEach(store.remove.bind(store))\n }\n\n return {\n store,\n authn,\n acl,\n resource,\n inbox,\n chat,\n profile,\n typeIndex,\n load,\n updatePromise,\n clearStore\n }\n}\n"],"mappings":";;;;;;;;;;;;AAoBA,SAAgB,EAAiB,GAA8D,GAA8C;CAEzI,EAAU,0EAA0E;CACpF,IAAM,IAAmB,EAAI,MAAM;CAGnC,AAFA,EAAI,QAAQ,GAAO,EAAC,OAAO,EAAa,MAAK,CAAC,GAC9C,EAAM,UAAU,IAAI,EAAI,cAAc,CAAK,GAC3C,EAAM,WAAW,CAAC;CAElB,IAAM,IAAoB,IAAI,EAAgB,CAAO,GAE/C,IAAM,EAAe,CAAK,GAC1B,IAAiB,EAAqB,CAAK,GAC3C,IAAe,EAAmB,GAAO,GAAK,CAAc,GAC5D,IAAU,EAAmB,GAAO,GAAO,CAAY,GACvD,IAAO,EAAgB,GAAO,CAAO,GACrC,IAAQ,EAAiB,GAAO,GAAS,GAAc,GAAgB,CAAG,GAC1E,IAAY,EAAqB,GAAO,GAAO,GAAS,CAAY,GACpE,IAAW,EAAoB,GAAO,GAAK,GAAgB,CAAS;CAC1E,EAAU,6BAA6B;CAEvC,SAAS,EAAK,GAAuC;EACjD,OAAO,EAAM,QAAQ,KAAK,CAAG;CACjC;CAGA,SAAS,EACL,GACA,IAAwB,CAAC,GACZ;EACb,OAAO,IAAI,SAAS,GAAS,MAAW;GACxC,EAAM,QAAQ,OAAO,GAAK,GAAK,SAAU,GAAM,GAAI,GAAW;IAC1D,AAAK,IAGL,EAAQ,IAFR,EAAW,MAAM,CAAS,CAAC;GAI/B,CAAC;EACD,CAAC;CACL;CAEA,SAAS,IAAa;EAClB,EAAM,WAAW,MAAM,CAAC,CAAC,QAAQ,EAAM,OAAO,KAAK,CAAK,CAAC;CAC7D;CAEA,OAAO;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACJ;AACJ"}
@@ -0,0 +1,2 @@
1
+ function e(e){return e?.status??e?.response?.status}function t(e){return e===404||e===410}function n(e,n,r={}){if(e.ok||r.allowNotFound&&t(e.status))return;let i=e.status===412?`Error: File changed by someone else`:`HTTP error on ${n}! Status: ${e.status}`;throw Error(i)}function r(n){if(t(e(n)))return!0;let r=`${n?.message||n||``}`;return r.includes(`404`)||r.includes(`Not Found`)}exports.assertSuccessfulHttpResponse=n,exports.isMissingError=r;
2
+ //# sourceMappingURL=resourceHttp.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceHttp.cjs.js","names":[],"sources":["../../src/resource/resourceHttp.ts"],"sourcesContent":["function getHttpStatus(value: { status?: number, response?: { status?: number } } | null | undefined) {\n return value?.status ?? value?.response?.status\n}\n\nfunction isMissingStatus(status: number | undefined) {\n return status === 404 || status === 410\n}\n\nexport function assertSuccessfulHttpResponse(response: Response, method: string, options: { allowNotFound?: boolean } = {}) {\n if (response.ok) return\n\n if (options.allowNotFound && isMissingStatus(response.status)) return\n\n const message = response.status === 412\n ? 'Error: File changed by someone else'\n : `HTTP error on ${method}! Status: ${response.status}`\n throw new Error(message)\n}\n\nexport function isMissingError(error: any): boolean {\n if (isMissingStatus(getHttpStatus(error))) return true\n const text = `${error?.message || error || ''}`\n return text.includes('404') || text.includes('Not Found')\n}\n"],"mappings":"AAAA,SAAS,EAAc,EAA+E,CACpG,OAAO,GAAO,QAAU,GAAO,UAAU,MAC3C,CAEA,SAAS,EAAgB,EAA4B,CACnD,OAAO,IAAW,KAAO,IAAW,GACtC,CAEA,SAAgB,EAA6B,EAAoB,EAAgB,EAAuC,CAAC,EAAG,CAG1H,GAFI,EAAS,IAET,EAAQ,eAAiB,EAAgB,EAAS,MAAM,EAAG,OAE/D,IAAM,EAAU,EAAS,SAAW,IAChC,sCACA,iBAAiB,EAAO,YAAY,EAAS,SACjD,MAAU,MAAM,CAAO,CACzB,CAEA,SAAgB,EAAe,EAAqB,CAClD,GAAI,EAAgB,EAAc,CAAK,CAAC,EAAG,MAAO,GAClD,IAAM,EAAO,GAAG,GAAO,SAAW,GAAS,KAC3C,OAAO,EAAK,SAAS,KAAK,GAAK,EAAK,SAAS,WAAW,CAC1D"}
@@ -0,0 +1,21 @@
1
+ //#region src/resource/resourceHttp.ts
2
+ function e(e) {
3
+ return e?.status ?? e?.response?.status;
4
+ }
5
+ function t(e) {
6
+ return e === 404 || e === 410;
7
+ }
8
+ function n(e, n, r = {}) {
9
+ if (e.ok || r.allowNotFound && t(e.status)) return;
10
+ let i = e.status === 412 ? "Error: File changed by someone else" : `HTTP error on ${n}! Status: ${e.status}`;
11
+ throw Error(i);
12
+ }
13
+ function r(n) {
14
+ if (t(e(n))) return !0;
15
+ let r = `${n?.message || n || ""}`;
16
+ return r.includes("404") || r.includes("Not Found");
17
+ }
18
+ //#endregion
19
+ export { n as assertSuccessfulHttpResponse, r as isMissingError };
20
+
21
+ //# sourceMappingURL=resourceHttp.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceHttp.esm.js","names":[],"sources":["../../src/resource/resourceHttp.ts"],"sourcesContent":["function getHttpStatus(value: { status?: number, response?: { status?: number } } | null | undefined) {\n return value?.status ?? value?.response?.status\n}\n\nfunction isMissingStatus(status: number | undefined) {\n return status === 404 || status === 410\n}\n\nexport function assertSuccessfulHttpResponse(response: Response, method: string, options: { allowNotFound?: boolean } = {}) {\n if (response.ok) return\n\n if (options.allowNotFound && isMissingStatus(response.status)) return\n\n const message = response.status === 412\n ? 'Error: File changed by someone else'\n : `HTTP error on ${method}! Status: ${response.status}`\n throw new Error(message)\n}\n\nexport function isMissingError(error: any): boolean {\n if (isMissingStatus(getHttpStatus(error))) return true\n const text = `${error?.message || error || ''}`\n return text.includes('404') || text.includes('Not Found')\n}\n"],"mappings":";AAAA,SAAS,EAAc,GAA+E;CACpG,OAAO,GAAO,UAAU,GAAO,UAAU;AAC3C;AAEA,SAAS,EAAgB,GAA4B;CACnD,OAAO,MAAW,OAAO,MAAW;AACtC;AAEA,SAAgB,EAA6B,GAAoB,GAAgB,IAAuC,CAAC,GAAG;CAG1H,IAFI,EAAS,MAET,EAAQ,iBAAiB,EAAgB,EAAS,MAAM,GAAG;CAE/D,IAAM,IAAU,EAAS,WAAW,MAChC,wCACA,iBAAiB,EAAO,YAAY,EAAS;CACjD,MAAU,MAAM,CAAO;AACzB;AAEA,SAAgB,EAAe,GAAqB;CAClD,IAAI,EAAgB,EAAc,CAAK,CAAC,GAAG,OAAO;CAClD,IAAM,IAAO,GAAG,GAAO,WAAW,KAAS;CAC3C,OAAO,EAAK,SAAS,KAAK,KAAK,EAAK,SAAS,WAAW;AAC1D"}
@@ -0,0 +1,2 @@
1
+ const e=require("../util/ns.cjs.js"),t=require("../acl/aclLogic.cjs.js"),n=require("./resourceHttp.cjs.js"),r=require("./resourceMetadata.cjs.js");let i=require("rdflib");function a(a,o,s,c){function l(e){return s.createContainer(e)}function u(e){return s.isContainer(e)}function d(e){return s.getContainerMemberCount(e)}function f(n,i){let o,s=!1,c=!1,l,u;if(i.headers){o=i.headers.get(`content-type`)?.split(`;`)[0]??void 0;let t=r.readWacAccessInfo(i.headers.get(`wac-allow`));s=t.canEdit,c=t.isPublic,l=i.headers.get(`etag`)??void 0,u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}(!i.headers||!i.headers.get(`content-type`))&&(!i.headers||!i.headers.get(`wac-allow`)||!i.headers.get(`etag`))&&a.each(null,a.sym(`http://www.w3.org/2007/ont/link#requestedURI`),n).map(t=>{let i=a.any(t,a.sym(`http://www.w3.org/2007/ont/link#response`));if(i&&i.termType===`NamedNode`){let t=a.anyValue(i,e.ns.httph(`content-type`))||void 0;o===void 0&&(o=t);let d=r.readWacAccessInfo(a.anyValue(i,e.ns.httph(`wac-allow`))||a.anyValue(i,e.ns.httph(`WAC-Allow`)));s||=d.canEdit,c||=d.isPublic;let f=a.anyValue(i,e.ns.httph(`etag`))||void 0;l===void 0&&(l=f),u=a.anyValue(n,e.ns.dct(`modified`))||a.anyValue(n,e.ns.dc(`modified`))||void 0}});let d=a.any(n,t.ACL_LINK)?.value||void 0;return{contentType:o,access:{canEdit:s,isPublic:c},aclUri:d,eTag:l,modified:u}}async function p(e){let t=await a.fetcher.webOperation(`HEAD`,e.uri);return n.assertSuccessfulHttpResponse(t,`HEAD`),f(e,t)}async function m(t){let n=a.any(t,e.ns.ldp(`contains`))||t.dir();if(!n||n.termType!==`NamedNode`)return!1;try{return(await p(n)).access.canEdit}catch{return!1}}async function h(e){return m(e)}async function g(e){return p(e)}async function _(e){let t;try{t=await p(e)}catch{t={contentType:void 0,access:{canEdit:!1,isPublic:!1},aclUri:void 0,eTag:void 0,modified:void 0}}let n=await h(e),r={canEdit:t.access?.canEdit??!1,isPublic:t.access?.isPublic??!1,canDelete:n};return{...t,access:r}}async function v(e,t){if(t)try{await c.deleteTypeIndexRegistrationForResource(e,t)}catch{}}async function y(t,r={}){let o=t.dir();if(u(t)){let e=await s.getContainerMembers(t);await Promise.all(e.map(e=>y((0,i.sym)(e),r)))}let c;try{c=await a.fetcher._fetch(t.value,{method:`DELETE`}),n.assertSuccessfulHttpResponse(c,`DELETE`,{allowNotFound:!0})}catch(e){if(!n.isMissingError(e))throw e}return r.deleteTypeIndexes&&await v(t,r.user),o&&a.removeMatches(o,e.ns.ldp(`contains`),t,o.doc()),a.removeDocument(t),a.fetcher.unload(t.doc()),c}async function b(e,t){await y(e,{deleteTypeIndexes:!0,user:t})}return{recursiveDelete:y,deleteResourceAndTypeIndexIfExists:b,fetchMetadata:g,fetchMetadataWithDelete:_,createContainer:l,isContainer:u,getContainerMemberCount:d}}exports.createResourceLogic=a;
2
+ //# sourceMappingURL=resourceLogic.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceLogic.cjs.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ import { ns as e } from "../util/ns.esm.js";
2
+ import { ACL_LINK as t } from "../acl/aclLogic.esm.js";
3
+ import { assertSuccessfulHttpResponse as n, isMissingError as r } from "./resourceHttp.esm.js";
4
+ import { readWacAccessInfo as i } from "./resourceMetadata.esm.js";
5
+ import { sym as a } from "rdflib";
6
+ //#region src/resource/resourceLogic.ts
7
+ function o(o, s, c, l) {
8
+ function u(e) {
9
+ return c.createContainer(e);
10
+ }
11
+ function d(e) {
12
+ return c.isContainer(e);
13
+ }
14
+ function f(e) {
15
+ return c.getContainerMemberCount(e);
16
+ }
17
+ function p(n, r) {
18
+ let a, s = !1, c = !1, l, u;
19
+ if (r.headers) {
20
+ a = r.headers.get("content-type")?.split(";")[0] ?? void 0;
21
+ let t = i(r.headers.get("wac-allow"));
22
+ s = t.canEdit, c = t.isPublic, l = r.headers.get("etag") ?? void 0, u = o.anyValue(n, e.dct("modified")) || o.anyValue(n, e.dc("modified")) || void 0;
23
+ }
24
+ (!r.headers || !r.headers.get("content-type")) && (!r.headers || !r.headers.get("wac-allow") || !r.headers.get("etag")) && o.each(null, o.sym("http://www.w3.org/2007/ont/link#requestedURI"), n).map((t) => {
25
+ let r = o.any(t, o.sym("http://www.w3.org/2007/ont/link#response"));
26
+ if (r && r.termType === "NamedNode") {
27
+ let t = o.anyValue(r, e.httph("content-type")) || void 0;
28
+ a === void 0 && (a = t);
29
+ let d = i(o.anyValue(r, e.httph("wac-allow")) || o.anyValue(r, e.httph("WAC-Allow")));
30
+ s ||= d.canEdit, c ||= d.isPublic;
31
+ let f = o.anyValue(r, e.httph("etag")) || void 0;
32
+ l === void 0 && (l = f), u = o.anyValue(n, e.dct("modified")) || o.anyValue(n, e.dc("modified")) || void 0;
33
+ }
34
+ });
35
+ let d = o.any(n, t)?.value || void 0;
36
+ return {
37
+ contentType: a,
38
+ access: {
39
+ canEdit: s,
40
+ isPublic: c
41
+ },
42
+ aclUri: d,
43
+ eTag: l,
44
+ modified: u
45
+ };
46
+ }
47
+ async function m(e) {
48
+ let t = await o.fetcher.webOperation("HEAD", e.uri);
49
+ return n(t, "HEAD"), p(e, t);
50
+ }
51
+ async function h(t) {
52
+ let n = o.any(t, e.ldp("contains")) || t.dir();
53
+ if (!n || n.termType !== "NamedNode") return !1;
54
+ try {
55
+ return (await m(n)).access.canEdit;
56
+ } catch {
57
+ return !1;
58
+ }
59
+ }
60
+ async function g(e) {
61
+ return h(e);
62
+ }
63
+ async function _(e) {
64
+ return m(e);
65
+ }
66
+ async function v(e) {
67
+ let t;
68
+ try {
69
+ t = await m(e);
70
+ } catch {
71
+ t = {
72
+ contentType: void 0,
73
+ access: {
74
+ canEdit: !1,
75
+ isPublic: !1
76
+ },
77
+ aclUri: void 0,
78
+ eTag: void 0,
79
+ modified: void 0
80
+ };
81
+ }
82
+ let n = await g(e), r = {
83
+ canEdit: t.access?.canEdit ?? !1,
84
+ isPublic: t.access?.isPublic ?? !1,
85
+ canDelete: n
86
+ };
87
+ return {
88
+ ...t,
89
+ access: r
90
+ };
91
+ }
92
+ async function y(e, t) {
93
+ if (t) try {
94
+ await l.deleteTypeIndexRegistrationForResource(e, t);
95
+ } catch {}
96
+ }
97
+ async function b(t, i = {}) {
98
+ let s = t.dir();
99
+ if (d(t)) {
100
+ let e = await c.getContainerMembers(t);
101
+ await Promise.all(e.map((e) => b(a(e), i)));
102
+ }
103
+ let l;
104
+ try {
105
+ l = await o.fetcher._fetch(t.value, { method: "DELETE" }), n(l, "DELETE", { allowNotFound: !0 });
106
+ } catch (e) {
107
+ if (!r(e)) throw e;
108
+ }
109
+ return i.deleteTypeIndexes && await y(t, i.user), s && o.removeMatches(s, e.ldp("contains"), t, s.doc()), o.removeDocument(t), o.fetcher.unload(t.doc()), l;
110
+ }
111
+ async function x(e, t) {
112
+ await b(e, {
113
+ deleteTypeIndexes: !0,
114
+ user: t
115
+ });
116
+ }
117
+ return {
118
+ recursiveDelete: b,
119
+ deleteResourceAndTypeIndexIfExists: x,
120
+ fetchMetadata: _,
121
+ fetchMetadataWithDelete: v,
122
+ createContainer: u,
123
+ isContainer: d,
124
+ getContainerMemberCount: f
125
+ };
126
+ }
127
+ //#endregion
128
+ export { o as createResourceLogic };
129
+
130
+ //# sourceMappingURL=resourceLogic.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceLogic.esm.js","names":[],"sources":["../../src/resource/resourceLogic.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport { ACL_LINK } from '../acl/aclLogic'\nimport { ns } from '../util/ns'\nimport { assertSuccessfulHttpResponse, isMissingError } from './resourceHttp'\nimport { readWacAccessInfo } from './resourceMetadata'\nimport { type AclLogic, type ResourceAccess, type ResourceAccessWithDelete, type ResourceDeleteOptions, type ResourceLogic, type ResourceMetadata, type ResourceMetadataWithDelete, type TypeIndexLogic } from '../types'\n\nexport function createResourceLogic(store, aclLogic: AclLogic, containerLogic, typeIndexLogic: TypeIndexLogic): ResourceLogic {\n function createContainer(url: string) {\n return containerLogic.createContainer(url)\n }\n\n function isContainer(resourceNode: NamedNode) {\n return containerLogic.isContainer(resourceNode)\n }\n\n function getContainerMemberCount(resourceNode: NamedNode) {\n return containerLogic.getContainerMemberCount(resourceNode)\n }\n\n function readMetadata(subject: NamedNode, response: Response): ResourceMetadata {\n let contentType: string | undefined\n let canEdit = false\n let isPublic = false\n let eTag: string | undefined\n let modified: string | undefined\n\n if (response.headers) {\n const contentTypeHeader = response.headers.get('content-type')\n contentType = contentTypeHeader?.split(';')[0] ?? undefined\n\n const accessFlags = readWacAccessInfo(response.headers.get('wac-allow'))\n canEdit = accessFlags.canEdit\n isPublic = accessFlags.isPublic\n eTag = response.headers.get('etag') ?? undefined\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n\n if ((!response.headers || !response.headers.get('content-type')) && (!response.headers || !response.headers.get('wac-allow') || !response.headers.get('etag'))) {\n const reqs = store.each(\n null,\n store.sym('http://www.w3.org/2007/ont/link#requestedURI'),\n subject\n )\n reqs.map((req: any) => {\n const responseNode = store.any(\n req as any,\n store.sym('http://www.w3.org/2007/ont/link#response')\n )\n if (responseNode && responseNode.termType === 'NamedNode') {\n const responseContentType = store.anyValue(responseNode as any, ns.httph('content-type')) || undefined\n if (contentType === undefined) {\n contentType = responseContentType\n }\n const wacAllow = (store.anyValue(responseNode as any, ns.httph('wac-allow')) as string | undefined) ||\n (store.anyValue(responseNode as any, ns.httph('WAC-Allow')) as string | undefined)\n const accessFlags = readWacAccessInfo(wacAllow)\n canEdit = canEdit || accessFlags.canEdit\n isPublic = isPublic || accessFlags.isPublic\n const responseETag = store.anyValue(responseNode as any, ns.httph('etag')) || undefined\n if (eTag === undefined) {\n eTag = responseETag\n }\n modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined\n }\n })\n }\n\n const aclUri = store.any(subject, ACL_LINK)?.value || undefined\n const access: ResourceAccess = { canEdit, isPublic }\n return { contentType, access, aclUri, eTag, modified }\n }\n\n async function fetchHeadMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n const response = await store.fetcher.webOperation('HEAD', subject.uri)\n assertSuccessfulHttpResponse(response, 'HEAD')\n return readMetadata(subject, response)\n }\n\n async function userCanWriteToContainingContainer(resourceNode: NamedNode): Promise<boolean> {\n const containerNode = store.any(resourceNode, ns.ldp('contains')) || resourceNode.dir()\n if (!containerNode || containerNode.termType !== 'NamedNode') {\n return false\n }\n\n try {\n const containerMetadata = await fetchHeadMetadata(containerNode as NamedNode)\n return containerMetadata.access.canEdit\n } catch (_error) {\n return false\n }\n }\n\n async function userCanDeleteResource(resourceNode: NamedNode): Promise<boolean> {\n return userCanWriteToContainingContainer(resourceNode)\n }\n\n async function fetchMetadata(subject: NamedNode): Promise<ResourceMetadata> {\n return fetchHeadMetadata(subject)\n }\n\n async function fetchMetadataWithDelete(subject: NamedNode): Promise<ResourceMetadataWithDelete> {\n let resourceMetadata: ResourceMetadata\n\n try {\n resourceMetadata = await fetchHeadMetadata(subject)\n } catch (_error) {\n resourceMetadata = {\n contentType: undefined,\n access: { canEdit: false, isPublic: false },\n aclUri: undefined,\n eTag: undefined,\n modified: undefined\n }\n }\n\n const canDelete = await userCanDeleteResource(subject)\n const access: ResourceAccessWithDelete = {\n canEdit: resourceMetadata.access?.canEdit ?? false,\n isPublic: resourceMetadata.access?.isPublic ?? false,\n canDelete\n }\n return { ...resourceMetadata, access }\n }\n\n async function deleteTypeIndexesForResource(resourceNode: NamedNode, user?: NamedNode | null) {\n if (!user) return\n\n try {\n await typeIndexLogic.deleteTypeIndexRegistrationForResource(resourceNode, user)\n } catch (_error) {\n // Keep resource deletion best-effort even if type-index cleanup fails.\n }\n }\n\n async function recursiveDelete(resourceNode: NamedNode, options: ResourceDeleteOptions = {}) {\n const resourceParent = resourceNode.dir()\n\n if (isContainer(resourceNode)) {\n const containerMembers = await containerLogic.getContainerMembers(resourceNode)\n await Promise.all(containerMembers.map((url) => recursiveDelete(sym(url), options)))\n }\n\n let deleted\n try {\n deleted = await store.fetcher._fetch(resourceNode.value, { method: 'DELETE' })\n assertSuccessfulHttpResponse(deleted, 'DELETE', { allowNotFound: true })\n } catch (error) {\n if (!isMissingError(error)) {\n throw error\n }\n }\n\n if (options.deleteTypeIndexes) {\n await deleteTypeIndexesForResource(resourceNode, options.user)\n }\n\n if (resourceParent) {\n store.removeMatches(resourceParent, ns.ldp('contains'), resourceNode, resourceParent.doc())\n }\n\n store.removeDocument(resourceNode)\n store.fetcher.unload(resourceNode.doc())\n return deleted\n }\n\n async function deleteResourceAndTypeIndexIfExists(resourceNode: NamedNode, user?: NamedNode | null) {\n await recursiveDelete(resourceNode, { deleteTypeIndexes: true, user })\n }\n\n return {\n recursiveDelete,\n deleteResourceAndTypeIndexIfExists,\n fetchMetadata,\n fetchMetadataWithDelete,\n createContainer,\n isContainer,\n getContainerMemberCount\n }\n}\n"],"mappings":";;;;;;AAOA,SAAgB,EAAoB,GAAO,GAAoB,GAAgB,GAA+C;CAC5H,SAAS,EAAgB,GAAa;EACpC,OAAO,EAAe,gBAAgB,CAAG;CAC3C;CAEA,SAAS,EAAY,GAAyB;EAC5C,OAAO,EAAe,YAAY,CAAY;CAChD;CAEA,SAAS,EAAwB,GAAyB;EACxD,OAAO,EAAe,wBAAwB,CAAY;CAC5D;CAEA,SAAS,EAAa,GAAoB,GAAsC;EAC9E,IAAI,GACA,IAAU,IACV,IAAW,IACX,GACA;EAEJ,IAAI,EAAS,SAAS;GAEpB,IAD0B,EAAS,QAAQ,IAAI,cACjC,CAAA,EAAmB,MAAM,GAAG,CAAC,CAAC,MAAM,KAAA;GAElD,IAAM,IAAc,EAAkB,EAAS,QAAQ,IAAI,WAAW,CAAC;GAIvE,AAHA,IAAU,EAAY,SACtB,IAAW,EAAY,UACvB,IAAO,EAAS,QAAQ,IAAI,MAAM,KAAK,KAAA,GACvC,IAAW,EAAM,SAAS,GAAgB,EAAG,IAAI,UAAU,CAAC,KAAK,EAAM,SAAS,GAAgB,EAAG,GAAG,UAAU,CAAC,KAAK,KAAA;EACxH;EAEA,CAAK,CAAC,EAAS,WAAW,CAAC,EAAS,QAAQ,IAAI,cAAc,OAAO,CAAC,EAAS,WAAW,CAAC,EAAS,QAAQ,IAAI,WAAW,KAAK,CAAC,EAAS,QAAQ,IAAI,MAAM,MAM1J,EALmB,KACjB,MACA,EAAM,IAAI,8CAA8C,GACxD,CAEF,CAAA,CAAK,KAAK,MAAa;GACrB,IAAM,IAAe,EAAM,IACzB,GACA,EAAM,IAAI,0CAA0C,CACtD;GACA,IAAI,KAAgB,EAAa,aAAa,aAAa;IACzD,IAAM,IAAsB,EAAM,SAAS,GAAqB,EAAG,MAAM,cAAc,CAAC,KAAK,KAAA;IAC7F,AAAI,MAAgB,KAAA,MAClB,IAAc;IAIhB,IAAM,IAAc,EAFF,EAAM,SAAS,GAAqB,EAAG,MAAM,WAAW,CAAC,KACxE,EAAM,SAAS,GAAqB,EAAG,MAAM,WAAW,CAAC,CACd;IAE9C,AADA,MAAqB,EAAY,SACjC,MAAuB,EAAY;IACnC,IAAM,IAAe,EAAM,SAAS,GAAqB,EAAG,MAAM,MAAM,CAAC,KAAK,KAAA;IAI9E,AAHI,MAAS,KAAA,MACX,IAAO,IAET,IAAW,EAAM,SAAS,GAAgB,EAAG,IAAI,UAAU,CAAC,KAAK,EAAM,SAAS,GAAgB,EAAG,GAAG,UAAU,CAAC,KAAK,KAAA;GACxH;EACF,CAAC;EAGH,IAAM,IAAS,EAAM,IAAI,GAAS,CAAQ,CAAC,EAAE,SAAS,KAAA;EAEtD,OAAO;GAAE;GAAa,QAAA;IADW;IAAS;GACpB;GAAQ;GAAQ;GAAM;EAAS;CACvD;CAEA,eAAe,EAAkB,GAA+C;EAC9E,IAAM,IAAW,MAAM,EAAM,QAAQ,aAAa,QAAQ,EAAQ,GAAG;EAErE,OADA,EAA6B,GAAU,MAAM,GACtC,EAAa,GAAS,CAAQ;CACvC;CAEA,eAAe,EAAkC,GAA2C;EAC1F,IAAM,IAAgB,EAAM,IAAI,GAAc,EAAG,IAAI,UAAU,CAAC,KAAK,EAAa,IAAI;EACtF,IAAI,CAAC,KAAiB,EAAc,aAAa,aAC/C,OAAO;EAGT,IAAI;GAEF,QAAO,MADyB,EAAkB,CAA0B,EAAA,CACnD,OAAO;EAClC,QAAiB;GACf,OAAO;EACT;CACF;CAEA,eAAe,EAAsB,GAA2C;EAC9E,OAAO,EAAkC,CAAY;CACvD;CAEA,eAAe,EAAc,GAA+C;EAC1E,OAAO,EAAkB,CAAO;CAClC;CAEA,eAAe,EAAwB,GAAyD;EAC9F,IAAI;EAEJ,IAAI;GACF,IAAmB,MAAM,EAAkB,CAAO;EACpD,QAAiB;GACf,IAAmB;IACjB,aAAa,KAAA;IACb,QAAQ;KAAE,SAAS;KAAO,UAAU;IAAM;IAC1C,QAAQ,KAAA;IACR,MAAM,KAAA;IACN,UAAU,KAAA;GACZ;EACF;EAEA,IAAM,IAAY,MAAM,EAAsB,CAAO,GAC/C,IAAmC;GACvC,SAAS,EAAiB,QAAQ,WAAW;GAC7C,UAAU,EAAiB,QAAQ,YAAY;GAC/C;EACF;EACA,OAAO;GAAE,GAAG;GAAkB;EAAO;CACvC;CAEA,eAAe,EAA6B,GAAyB,GAAyB;EACvF,OAEL,IAAI;GACF,MAAM,EAAe,uCAAuC,GAAc,CAAI;EAChF,QAAiB,CAEjB;CACF;CAEA,eAAe,EAAgB,GAAyB,IAAiC,CAAC,GAAG;EAC3F,IAAM,IAAiB,EAAa,IAAI;EAExC,IAAI,EAAY,CAAY,GAAG;GAC7B,IAAM,IAAmB,MAAM,EAAe,oBAAoB,CAAY;GAC9E,MAAM,QAAQ,IAAI,EAAiB,KAAK,MAAQ,EAAgB,EAAI,CAAG,GAAG,CAAO,CAAC,CAAC;EACrF;EAEA,IAAI;EACJ,IAAI;GAEF,AADA,IAAU,MAAM,EAAM,QAAQ,OAAO,EAAa,OAAO,EAAE,QAAQ,SAAS,CAAC,GAC7E,EAA6B,GAAS,UAAU,EAAE,eAAe,GAAK,CAAC;EACzE,SAAS,GAAO;GACd,IAAI,CAAC,EAAe,CAAK,GACvB,MAAM;EAEV;EAYA,OAVI,EAAQ,qBACV,MAAM,EAA6B,GAAc,EAAQ,IAAI,GAG3D,KACF,EAAM,cAAc,GAAgB,EAAG,IAAI,UAAU,GAAG,GAAc,EAAe,IAAI,CAAC,GAG5F,EAAM,eAAe,CAAY,GACjC,EAAM,QAAQ,OAAO,EAAa,IAAI,CAAC,GAChC;CACT;CAEA,eAAe,EAAmC,GAAyB,GAAyB;EAClG,MAAM,EAAgB,GAAc;GAAE,mBAAmB;GAAM;EAAK,CAAC;CACvE;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -0,0 +1,2 @@
1
+ function e(e){let t=new Map;if(!e)return t;for(let n of e.split(`,`)){let e=n.trim().match(/^([A-Za-z]+)\s*=\s*"([^"]*)"$/);if(e){let[,n,r]=e,i=r.trim().split(/\s+/).filter(Boolean);t.set(n.toLowerCase(),new Set(i.map(e=>e.toLowerCase())))}}return t}function t(t){if(!t)return{canEdit:!1,isPublic:!1};let n=e(t),r=n.get(`user`)??new Set,i=n.get(`public`)??new Set;return{canEdit:r.has(`write`),isPublic:i.has(`read`)||i.has(`write`)}}exports.readWacAccessInfo=t;
2
+ //# sourceMappingURL=resourceMetadata.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceMetadata.cjs.js","names":[],"sources":["../../src/resource/resourceMetadata.ts"],"sourcesContent":["function parseWacAllowHeader (headerValue: string | null | undefined) {\n const permissions = new Map<string, Set<string>>()\n if (!headerValue) return permissions\n\n for (const entry of headerValue.split(',')) {\n const match = entry.trim().match(/^([A-Za-z]+)\\s*=\\s*\"([^\"]*)\"$/)\n if (match) {\n const [, permissionGroup, accessModes] = match\n const modes = accessModes.trim().split(/\\s+/).filter(Boolean)\n permissions.set(permissionGroup.toLowerCase(), new Set(modes.map(mode => mode.toLowerCase())))\n }\n }\n\n return permissions\n}\n\nexport function readWacAccessInfo (wacAllow: string | null | undefined) {\n if (!wacAllow) {\n return { canEdit: false, isPublic: false }\n }\n\n const permissions = parseWacAllowHeader(wacAllow)\n const userModes = permissions.get('user') ?? new Set<string>()\n const publicModes = permissions.get('public') ?? new Set<string>()\n\n return {\n canEdit: userModes.has('write'),\n isPublic: publicModes.has('read') || publicModes.has('write')\n }\n}\n"],"mappings":"AAAA,SAAS,EAAqB,EAAwC,CACpE,IAAM,EAAc,IAAI,IACxB,GAAI,CAAC,EAAa,OAAO,EAEzB,IAAK,IAAM,KAAS,EAAY,MAAM,GAAG,EAAG,CAC1C,IAAM,EAAQ,EAAM,KAAK,CAAC,CAAC,MAAM,+BAA+B,EAChE,GAAI,EAAO,CACT,GAAM,EAAG,EAAiB,GAAe,EACnC,EAAQ,EAAY,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO,EAC5D,EAAY,IAAI,EAAgB,YAAY,EAAG,IAAI,IAAI,EAAM,IAAI,GAAQ,EAAK,YAAY,CAAC,CAAC,CAAC,CAC/F,CACF,CAEA,OAAO,CACT,CAEA,SAAgB,EAAmB,EAAqC,CACtE,GAAI,CAAC,EACH,MAAO,CAAE,QAAS,GAAO,SAAU,EAAM,EAG3C,IAAM,EAAc,EAAoB,CAAQ,EAC1C,EAAY,EAAY,IAAI,MAAM,GAAK,IAAI,IAC3C,EAAc,EAAY,IAAI,QAAQ,GAAK,IAAI,IAErD,MAAO,CACL,QAAS,EAAU,IAAI,OAAO,EAC9B,SAAU,EAAY,IAAI,MAAM,GAAK,EAAY,IAAI,OAAO,CAC9D,CACF"}
@@ -0,0 +1,28 @@
1
+ //#region src/resource/resourceMetadata.ts
2
+ function e(e) {
3
+ let t = /* @__PURE__ */ new Map();
4
+ if (!e) return t;
5
+ for (let n of e.split(",")) {
6
+ let e = n.trim().match(/^([A-Za-z]+)\s*=\s*"([^"]*)"$/);
7
+ if (e) {
8
+ let [, n, r] = e, i = r.trim().split(/\s+/).filter(Boolean);
9
+ t.set(n.toLowerCase(), new Set(i.map((e) => e.toLowerCase())));
10
+ }
11
+ }
12
+ return t;
13
+ }
14
+ function t(t) {
15
+ if (!t) return {
16
+ canEdit: !1,
17
+ isPublic: !1
18
+ };
19
+ let n = e(t), r = n.get("user") ?? /* @__PURE__ */ new Set(), i = n.get("public") ?? /* @__PURE__ */ new Set();
20
+ return {
21
+ canEdit: r.has("write"),
22
+ isPublic: i.has("read") || i.has("write")
23
+ };
24
+ }
25
+ //#endregion
26
+ export { t as readWacAccessInfo };
27
+
28
+ //# sourceMappingURL=resourceMetadata.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceMetadata.esm.js","names":[],"sources":["../../src/resource/resourceMetadata.ts"],"sourcesContent":["function parseWacAllowHeader (headerValue: string | null | undefined) {\n const permissions = new Map<string, Set<string>>()\n if (!headerValue) return permissions\n\n for (const entry of headerValue.split(',')) {\n const match = entry.trim().match(/^([A-Za-z]+)\\s*=\\s*\"([^\"]*)\"$/)\n if (match) {\n const [, permissionGroup, accessModes] = match\n const modes = accessModes.trim().split(/\\s+/).filter(Boolean)\n permissions.set(permissionGroup.toLowerCase(), new Set(modes.map(mode => mode.toLowerCase())))\n }\n }\n\n return permissions\n}\n\nexport function readWacAccessInfo (wacAllow: string | null | undefined) {\n if (!wacAllow) {\n return { canEdit: false, isPublic: false }\n }\n\n const permissions = parseWacAllowHeader(wacAllow)\n const userModes = permissions.get('user') ?? new Set<string>()\n const publicModes = permissions.get('public') ?? new Set<string>()\n\n return {\n canEdit: userModes.has('write'),\n isPublic: publicModes.has('read') || publicModes.has('write')\n }\n}\n"],"mappings":";AAAA,SAAS,EAAqB,GAAwC;CACpE,IAAM,oBAAc,IAAI,IAAyB;CACjD,IAAI,CAAC,GAAa,OAAO;CAEzB,KAAK,IAAM,KAAS,EAAY,MAAM,GAAG,GAAG;EAC1C,IAAM,IAAQ,EAAM,KAAK,CAAC,CAAC,MAAM,+BAA+B;EAChE,IAAI,GAAO;GACT,IAAM,GAAG,GAAiB,KAAe,GACnC,IAAQ,EAAY,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;GAC5D,EAAY,IAAI,EAAgB,YAAY,GAAG,IAAI,IAAI,EAAM,KAAI,MAAQ,EAAK,YAAY,CAAC,CAAC,CAAC;EAC/F;CACF;CAEA,OAAO;AACT;AAEA,SAAgB,EAAmB,GAAqC;CACtE,IAAI,CAAC,GACH,OAAO;EAAE,SAAS;EAAO,UAAU;CAAM;CAG3C,IAAM,IAAc,EAAoB,CAAQ,GAC1C,IAAY,EAAY,IAAI,MAAM,qBAAK,IAAI,IAAY,GACvD,IAAc,EAAY,IAAI,QAAQ,qBAAK,IAAI,IAAY;CAEjE,OAAO;EACL,SAAS,EAAU,IAAI,OAAO;EAC9B,UAAU,EAAY,IAAI,MAAM,KAAK,EAAY,IAAI,OAAO;CAC9D;AACF"}