solid-logic 6.0.0-2 → 6.0.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs.js +1 -1
  2. package/dist/acl/accessControlSubjects.cjs.js +2 -0
  3. package/dist/acl/accessControlSubjects.cjs.js.map +1 -0
  4. package/dist/acl/accessControlSubjects.d.ts +8 -0
  5. package/dist/acl/accessControlSubjects.d.ts.map +1 -0
  6. package/dist/acl/accessControlSubjects.esm.js +75 -0
  7. package/dist/acl/accessControlSubjects.esm.js.map +1 -0
  8. package/dist/acl/aclLogic.cjs.js +1 -1
  9. package/dist/acl/aclLogic.cjs.js.map +1 -1
  10. package/dist/acl/aclLogic.d.ts +7 -0
  11. package/dist/acl/aclLogic.d.ts.map +1 -0
  12. package/dist/acl/aclLogic.esm.js +111 -27
  13. package/dist/acl/aclLogic.esm.js.map +1 -1
  14. package/dist/authSession/authSession.cjs.js.map +1 -1
  15. package/dist/authSession/authSession.d.ts +42 -0
  16. package/dist/authSession/authSession.d.ts.map +1 -0
  17. package/dist/authSession/authSession.esm.js.map +1 -1
  18. package/dist/authSession/events.cjs.js.map +1 -1
  19. package/dist/authSession/events.d.ts +25 -0
  20. package/dist/authSession/events.d.ts.map +1 -0
  21. package/dist/authSession/events.esm.js.map +1 -1
  22. package/dist/authSession/flagAuthorizationOnTransitions.cjs.js +1 -1
  23. package/dist/authSession/flagAuthorizationOnTransitions.cjs.js.map +1 -1
  24. package/dist/authSession/flagAuthorizationOnTransitions.d.ts +76 -0
  25. package/dist/authSession/flagAuthorizationOnTransitions.d.ts.map +1 -0
  26. package/dist/authSession/flagAuthorizationOnTransitions.esm.js +1 -1
  27. package/dist/authSession/flagAuthorizationOnTransitions.esm.js.map +1 -1
  28. package/dist/authSession/identityState.cjs.js +1 -1
  29. package/dist/authSession/identityState.cjs.js.map +1 -1
  30. package/dist/authSession/identityState.d.ts +199 -0
  31. package/dist/authSession/identityState.d.ts.map +1 -0
  32. package/dist/authSession/identityState.esm.js +1 -1
  33. package/dist/authSession/identityState.esm.js.map +1 -1
  34. package/dist/authSession/issuer.d.ts +8 -0
  35. package/dist/authSession/issuer.d.ts.map +1 -0
  36. package/dist/authSession/session.cjs.js +1 -1
  37. package/dist/authSession/session.cjs.js.map +1 -1
  38. package/dist/authSession/session.d.ts +45 -0
  39. package/dist/authSession/session.d.ts.map +1 -0
  40. package/dist/authSession/session.esm.js +1 -1
  41. package/dist/authSession/session.esm.js.map +1 -1
  42. package/dist/authn/SolidAuthnLogic.cjs.js.map +1 -1
  43. package/dist/authn/SolidAuthnLogic.d.ts +61 -0
  44. package/dist/authn/SolidAuthnLogic.d.ts.map +1 -0
  45. package/dist/authn/SolidAuthnLogic.esm.js.map +1 -1
  46. package/dist/authn/authUtil.cjs.js.map +1 -1
  47. package/dist/authn/authUtil.d.ts +17 -0
  48. package/dist/authn/authUtil.d.ts.map +1 -0
  49. package/dist/authn/serverLogout.d.ts +6 -0
  50. package/dist/authn/serverLogout.d.ts.map +1 -0
  51. package/dist/chat/chatLogic.cjs.js +1 -1
  52. package/dist/chat/chatLogic.cjs.js.map +1 -1
  53. package/dist/chat/chatLogic.d.ts +3 -0
  54. package/dist/chat/chatLogic.d.ts.map +1 -0
  55. package/dist/chat/chatLogic.esm.js +5 -5
  56. package/dist/chat/chatLogic.esm.js.map +1 -1
  57. package/dist/directory/catalogDirectory.cjs.js +2 -0
  58. package/dist/directory/catalogDirectory.cjs.js.map +1 -0
  59. package/dist/directory/catalogDirectory.d.ts +5 -0
  60. package/dist/directory/catalogDirectory.d.ts.map +1 -0
  61. package/dist/directory/catalogDirectory.esm.js +54 -0
  62. package/dist/directory/catalogDirectory.esm.js.map +1 -0
  63. package/dist/directory/contactsDirectory.cjs.js +2 -0
  64. package/dist/directory/contactsDirectory.cjs.js.map +1 -0
  65. package/dist/directory/contactsDirectory.d.ts +7 -0
  66. package/dist/directory/contactsDirectory.d.ts.map +1 -0
  67. package/dist/directory/contactsDirectory.esm.js +91 -0
  68. package/dist/directory/contactsDirectory.esm.js.map +1 -0
  69. package/dist/directory/directoryHelpers.cjs.js +2 -0
  70. package/dist/directory/directoryHelpers.cjs.js.map +1 -0
  71. package/dist/directory/directoryHelpers.d.ts +18 -0
  72. package/dist/directory/directoryHelpers.d.ts.map +1 -0
  73. package/dist/directory/directoryHelpers.esm.js +89 -0
  74. package/dist/directory/directoryHelpers.esm.js.map +1 -0
  75. package/dist/directory/directoryLogic.cjs.js +2 -0
  76. package/dist/directory/directoryLogic.cjs.js.map +1 -0
  77. package/dist/directory/directoryLogic.d.ts +6 -0
  78. package/dist/directory/directoryLogic.d.ts.map +1 -0
  79. package/dist/directory/directoryLogic.esm.js +41 -0
  80. package/dist/directory/directoryLogic.esm.js.map +1 -0
  81. package/dist/directory/friendsDirectory.cjs.js +2 -0
  82. package/dist/directory/friendsDirectory.cjs.js.map +1 -0
  83. package/dist/directory/friendsDirectory.d.ts +6 -0
  84. package/dist/directory/friendsDirectory.d.ts.map +1 -0
  85. package/dist/directory/friendsDirectory.esm.js +58 -0
  86. package/dist/directory/friendsDirectory.esm.js.map +1 -0
  87. package/dist/inbox/inboxLogic.d.ts +3 -0
  88. package/dist/inbox/inboxLogic.d.ts.map +1 -0
  89. package/dist/index.cjs.js +1 -1
  90. package/dist/index.cjs.js.map +1 -1
  91. package/dist/index.d.ts +19 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.esm.js +10 -9
  94. package/dist/index.esm.js.map +1 -1
  95. package/dist/issuer/issuerLogic.d.ts +8 -0
  96. package/dist/issuer/issuerLogic.d.ts.map +1 -0
  97. package/dist/logic/CustomError.cjs.js.map +1 -1
  98. package/dist/logic/CustomError.d.ts +21 -0
  99. package/dist/logic/CustomError.d.ts.map +1 -0
  100. package/dist/logic/CustomError.esm.js.map +1 -1
  101. package/dist/logic/solidLogic.cjs.js +1 -1
  102. package/dist/logic/solidLogic.cjs.js.map +1 -1
  103. package/dist/logic/solidLogic.d.ts +6 -0
  104. package/dist/logic/solidLogic.d.ts.map +1 -0
  105. package/dist/logic/solidLogic.esm.js +29 -27
  106. package/dist/logic/solidLogic.esm.js.map +1 -1
  107. package/dist/logic/solidLogicSingleton.cjs.js +1 -1
  108. package/dist/logic/solidLogicSingleton.cjs.js.map +1 -1
  109. package/dist/logic/solidLogicSingleton.d.ts +4 -0
  110. package/dist/logic/solidLogicSingleton.d.ts.map +1 -0
  111. package/dist/logic/solidLogicSingleton.esm.js +2 -1
  112. package/dist/logic/solidLogicSingleton.esm.js.map +1 -1
  113. package/dist/profile/profileAclDocuments.d.ts +2 -0
  114. package/dist/profile/profileAclDocuments.d.ts.map +1 -0
  115. package/dist/profile/profileDocuments.d.ts +2 -0
  116. package/dist/profile/profileDocuments.d.ts.map +1 -0
  117. package/dist/profile/profileLogic.cjs.js.map +1 -1
  118. package/dist/profile/profileLogic.d.ts +3 -0
  119. package/dist/profile/profileLogic.d.ts.map +1 -0
  120. package/dist/profile/profileLogic.esm.js +2 -1
  121. package/dist/profile/profileLogic.esm.js.map +1 -1
  122. package/dist/resource/resourceHttp.d.ts +5 -0
  123. package/dist/resource/resourceHttp.d.ts.map +1 -0
  124. package/dist/resource/resourceLogic.cjs.js +1 -1
  125. package/dist/resource/resourceLogic.cjs.js.map +1 -1
  126. package/dist/resource/resourceLogic.d.ts +4 -0
  127. package/dist/resource/resourceLogic.d.ts.map +1 -0
  128. package/dist/resource/resourceLogic.esm.js +36 -26
  129. package/dist/resource/resourceLogic.esm.js.map +1 -1
  130. package/dist/resource/resourceMetadata.d.ts +5 -0
  131. package/dist/resource/resourceMetadata.d.ts.map +1 -0
  132. package/dist/typeIndex/typeIndexAclDocuments.d.ts +2 -0
  133. package/dist/typeIndex/typeIndexAclDocuments.d.ts.map +1 -0
  134. package/dist/typeIndex/typeIndexDocuments.d.ts +3 -0
  135. package/dist/typeIndex/typeIndexDocuments.d.ts.map +1 -0
  136. package/dist/typeIndex/typeIndexLogic.cjs.js.map +1 -1
  137. package/dist/typeIndex/typeIndexLogic.d.ts +3 -0
  138. package/dist/typeIndex/typeIndexLogic.d.ts.map +1 -0
  139. package/dist/typeIndex/typeIndexLogic.esm.js +10 -5
  140. package/dist/typeIndex/typeIndexLogic.esm.js.map +1 -1
  141. package/dist/types.d.ts +187 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/util/containerLogic.cjs.js.map +1 -1
  144. package/dist/util/containerLogic.d.ts +12 -0
  145. package/dist/util/containerLogic.d.ts.map +1 -0
  146. package/dist/util/containerLogic.esm.js.map +1 -1
  147. package/dist/util/debug.d.ts +5 -0
  148. package/dist/util/debug.d.ts.map +1 -0
  149. package/dist/util/ns.cjs.js.map +1 -1
  150. package/dist/util/ns.d.ts +2 -0
  151. package/dist/util/ns.d.ts.map +1 -0
  152. package/dist/util/utilityLogic.cjs.js +1 -1
  153. package/dist/util/utilityLogic.cjs.js.map +1 -1
  154. package/dist/util/utilityLogic.d.ts +16 -0
  155. package/dist/util/utilityLogic.d.ts.map +1 -0
  156. package/dist/util/utilityLogic.esm.js +6 -2
  157. package/dist/util/utilityLogic.esm.js.map +1 -1
  158. package/dist/util/utils.cjs.js +1 -1
  159. package/dist/util/utils.cjs.js.map +1 -1
  160. package/dist/util/utils.d.ts +8 -0
  161. package/dist/util/utils.d.ts.map +1 -0
  162. package/dist/util/utils.esm.js +5 -3
  163. package/dist/util/utils.esm.js.map +1 -1
  164. package/package.json +6 -4
@@ -1 +1 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));exports.__toESM=s;
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));exports.__toESM=s;
@@ -0,0 +1,2 @@
1
+ const e=require("../util/ns.cjs.js");let t=require("rdflib");var n={agentClass:[e.ns.foaf(`Agent`),e.ns.acl(`AuthenticatedAgent`),e.ns.rdf(`Resource`),e.ns.owl(`Thing`)],agent:[e.ns.vcard(`WebID`),e.ns.vcard(`Individual`),e.ns.foaf(`Person`),e.ns.foaf(`Agent`)],agentGroup:[e.ns.vcard(`Group`)],origin:[e.ns.solid(`AppProvider`),e.ns.solid(`AppProviderClass`)]};function r(e){return Object.keys(e).length>0}function i(e){return e.startsWith(`http://`)||e.startsWith(`https://`)}function a(e){try{let t=new URL(e);return(t.protocol===`http:`||t.protocol===`https:`)&&t.pathname===`/`&&!t.search&&!t.hash}catch{return!1}}function o(e){try{let t=new URL(e);if((t.protocol===`http:`||t.protocol===`https:`)&&t.pathname===`/`&&!t.search&&!t.hash)return`${t.protocol}//${t.host}`}catch{}return e}async function s(s,c){let l=(0,t.sym)(c),u=s.findTypeURIs(l);if(a(c))return{kind:`origin`,subjectValue:o(c)};if(!r(u)&&i(c)){try{await s.fetcher.load(l.doc())}catch(e){console.error(`Failed to load access target ${c}`,e)}u=s.findTypeURIs(l)}if(n.origin.some(e=>e.uri in u))return{kind:`origin`,subjectValue:c};if(n.agent.some(e=>e.uri in u))return{kind:`agent`,subjectValue:s.any(l,e.ns.foaf(`preferredURI`))?.value??c};if(n.agentGroup.some(e=>e.uri in u))return{kind:`agentGroup`,subjectValue:c};if(n.agentClass.some(e=>l.sameTerm(e)))return{kind:`agentClass`,subjectValue:c}}exports.classifyAccessControlSubject=s;
2
+ //# sourceMappingURL=accessControlSubjects.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessControlSubjects.cjs.js","names":[],"sources":["../../src/acl/accessControlSubjects.ts"],"sourcesContent":["import { LiveStore, sym } from 'rdflib'\nimport { ns } from '../util/ns'\n\nexport type AccessControlSubjectKind = 'agent' | 'agentGroup' | 'agentClass' | 'origin'\n\nexport type AccessControlSubject = {\n kind: AccessControlSubjectKind\n subjectValue: string\n}\n\nconst ACCESS_CONTROL_SUBJECT_GROUPS = {\n agentClass: [ns.foaf('Agent'), ns.acl('AuthenticatedAgent'), ns.rdf('Resource'), ns.owl('Thing')],\n agent: [ns.vcard('WebID'), ns.vcard('Individual'), ns.foaf('Person'), ns.foaf('Agent')],\n agentGroup: [ns.vcard('Group')],\n origin: [ns.solid('AppProvider'), ns.solid('AppProviderClass')]\n} as const\n\nfunction hasKnownTypes (types: Record<string, unknown>): boolean {\n return Object.keys(types).length > 0\n}\n\nfunction isHttpUrl (value: string): boolean {\n return value.startsWith('http://') || value.startsWith('https://')\n}\n\nfunction isBareOriginUrl (value: string): boolean {\n try {\n const parsed = new URL(value)\n return (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n parsed.pathname === '/' &&\n !parsed.search &&\n !parsed.hash\n } catch (_error) {\n return false\n }\n}\n\nfunction normalizeOriginUrl (value: string): string {\n try {\n const parsed = new URL(value)\n if (\n (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n parsed.pathname === '/' &&\n !parsed.search &&\n !parsed.hash\n ) {\n return `${parsed.protocol}//${parsed.host}`\n }\n } catch (_error) {\n // Return the original value below when parsing fails.\n }\n\n return value\n}\n\nexport async function classifyAccessControlSubject (store: LiveStore, principle: string): Promise<AccessControlSubject | undefined> {\n const subject = sym(principle)\n let types = store.findTypeURIs(subject)\n\n if (isBareOriginUrl(principle)) {\n return { kind: 'origin', subjectValue: normalizeOriginUrl(principle) }\n }\n\n if (!hasKnownTypes(types) && isHttpUrl(principle)) {\n try {\n await store.fetcher.load(subject.doc())\n } catch (error) {\n console.error(`Failed to load access target ${principle}`, error)\n }\n\n types = store.findTypeURIs(subject)\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.origin.some(term => term.uri in types)) {\n return { kind: 'origin', subjectValue: principle }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agent.some(term => term.uri in types)) {\n const preferredURI = store.any(subject, ns.foaf('preferredURI'))\n return {\n kind: 'agent',\n subjectValue: preferredURI?.value ?? principle\n }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agentGroup.some(term => term.uri in types)) {\n return { kind: 'agentGroup', subjectValue: principle }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agentClass.some(term => subject.sameTerm(term))) {\n return { kind: 'agentClass', subjectValue: principle }\n }\n\n return undefined\n}\n"],"mappings":"6DAUA,IAAM,EAAgC,CAClC,WAAY,CAAC,EAAA,GAAG,KAAK,OAAO,EAAG,EAAA,GAAG,IAAI,oBAAoB,EAAG,EAAA,GAAG,IAAI,UAAU,EAAG,EAAA,GAAG,IAAI,OAAO,CAAC,EAChG,MAAO,CAAC,EAAA,GAAG,MAAM,OAAO,EAAG,EAAA,GAAG,MAAM,YAAY,EAAG,EAAA,GAAG,KAAK,QAAQ,EAAG,EAAA,GAAG,KAAK,OAAO,CAAC,EACtF,WAAY,CAAC,EAAA,GAAG,MAAM,OAAO,CAAC,EAC9B,OAAQ,CAAC,EAAA,GAAG,MAAM,aAAa,EAAG,EAAA,GAAG,MAAM,kBAAkB,CAAC,CAClE,EAEA,SAAS,EAAe,EAAyC,CAC7D,OAAO,OAAO,KAAK,CAAK,CAAC,CAAC,OAAS,CACvC,CAEA,SAAS,EAAW,EAAwB,CACxC,OAAO,EAAM,WAAW,SAAS,GAAK,EAAM,WAAW,UAAU,CACrE,CAEA,SAAS,EAAiB,EAAwB,CAC9C,GAAI,CACA,IAAM,EAAS,IAAI,IAAI,CAAK,EAC5B,OAAQ,EAAO,WAAa,SAAW,EAAO,WAAa,WACvD,EAAO,WAAa,KACpB,CAAC,EAAO,QACR,CAAC,EAAO,IAChB,MAAiB,CACb,MAAO,EACX,CACJ,CAEA,SAAS,EAAoB,EAAuB,CAChD,GAAI,CACA,IAAM,EAAS,IAAI,IAAI,CAAK,EAC5B,IACK,EAAO,WAAa,SAAW,EAAO,WAAa,WACpD,EAAO,WAAa,KACpB,CAAC,EAAO,QACR,CAAC,EAAO,KAER,MAAO,GAAG,EAAO,SAAS,IAAI,EAAO,MAE7C,MAAiB,CAEjB,CAEA,OAAO,CACX,CAEA,eAAsB,EAA8B,EAAkB,EAA8D,CAChI,IAAM,GAAA,EAAU,EAAA,IAAA,CAAI,CAAS,EACzB,EAAQ,EAAM,aAAa,CAAO,EAEtC,GAAI,EAAgB,CAAS,EACzB,MAAO,CAAE,KAAM,SAAU,aAAc,EAAmB,CAAS,CAAE,EAGzE,GAAI,CAAC,EAAc,CAAK,GAAK,EAAU,CAAS,EAAG,CAC/C,GAAI,CACA,MAAM,EAAM,QAAQ,KAAK,EAAQ,IAAI,CAAC,CAC1C,OAAS,EAAO,CACZ,QAAQ,MAAM,gCAAgC,IAAa,CAAK,CACpE,CAEA,EAAQ,EAAM,aAAa,CAAO,CACtC,CAEA,GAAI,EAA8B,OAAO,KAAK,GAAQ,EAAK,OAAO,CAAK,EACnE,MAAO,CAAE,KAAM,SAAU,aAAc,CAAU,EAGrD,GAAI,EAA8B,MAAM,KAAK,GAAQ,EAAK,OAAO,CAAK,EAElE,MAAO,CACH,KAAM,QACN,aAHiB,EAAM,IAAI,EAAS,EAAA,GAAG,KAAK,cAAc,CAG5C,CAAA,EAAc,OAAS,CACzC,EAGJ,GAAI,EAA8B,WAAW,KAAK,GAAQ,EAAK,OAAO,CAAK,EACvE,MAAO,CAAE,KAAM,aAAc,aAAc,CAAU,EAGzD,GAAI,EAA8B,WAAW,KAAK,GAAQ,EAAQ,SAAS,CAAI,CAAC,EAC5E,MAAO,CAAE,KAAM,aAAc,aAAc,CAAU,CAI7D"}
@@ -0,0 +1,8 @@
1
+ import { LiveStore } from 'rdflib';
2
+ export type AccessControlSubjectKind = 'agent' | 'agentGroup' | 'agentClass' | 'origin';
3
+ export type AccessControlSubject = {
4
+ kind: AccessControlSubjectKind;
5
+ subjectValue: string;
6
+ };
7
+ export declare function classifyAccessControlSubject(store: LiveStore, principle: string): Promise<AccessControlSubject | undefined>;
8
+ //# sourceMappingURL=accessControlSubjects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessControlSubjects.d.ts","sourceRoot":"","sources":["../../src/acl/accessControlSubjects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAO,MAAM,QAAQ,CAAA;AAGvC,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAA;AAEvF,MAAM,MAAM,oBAAoB,GAAG;IAC/B,IAAI,EAAE,wBAAwB,CAAA;IAC9B,YAAY,EAAE,MAAM,CAAA;CACvB,CAAA;AA+CD,wBAAsB,4BAA4B,CAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAuClI"}
@@ -0,0 +1,75 @@
1
+ import { ns as e } from "../util/ns.esm.js";
2
+ import { sym as t } from "rdflib";
3
+ //#region src/acl/accessControlSubjects.ts
4
+ var n = {
5
+ agentClass: [
6
+ e.foaf("Agent"),
7
+ e.acl("AuthenticatedAgent"),
8
+ e.rdf("Resource"),
9
+ e.owl("Thing")
10
+ ],
11
+ agent: [
12
+ e.vcard("WebID"),
13
+ e.vcard("Individual"),
14
+ e.foaf("Person"),
15
+ e.foaf("Agent")
16
+ ],
17
+ agentGroup: [e.vcard("Group")],
18
+ origin: [e.solid("AppProvider"), e.solid("AppProviderClass")]
19
+ };
20
+ function r(e) {
21
+ return Object.keys(e).length > 0;
22
+ }
23
+ function i(e) {
24
+ return e.startsWith("http://") || e.startsWith("https://");
25
+ }
26
+ function a(e) {
27
+ try {
28
+ let t = new URL(e);
29
+ return (t.protocol === "http:" || t.protocol === "https:") && t.pathname === "/" && !t.search && !t.hash;
30
+ } catch {
31
+ return !1;
32
+ }
33
+ }
34
+ function o(e) {
35
+ try {
36
+ let t = new URL(e);
37
+ if ((t.protocol === "http:" || t.protocol === "https:") && t.pathname === "/" && !t.search && !t.hash) return `${t.protocol}//${t.host}`;
38
+ } catch {}
39
+ return e;
40
+ }
41
+ async function s(s, c) {
42
+ let l = t(c), u = s.findTypeURIs(l);
43
+ if (a(c)) return {
44
+ kind: "origin",
45
+ subjectValue: o(c)
46
+ };
47
+ if (!r(u) && i(c)) {
48
+ try {
49
+ await s.fetcher.load(l.doc());
50
+ } catch (e) {
51
+ console.error(`Failed to load access target ${c}`, e);
52
+ }
53
+ u = s.findTypeURIs(l);
54
+ }
55
+ if (n.origin.some((e) => e.uri in u)) return {
56
+ kind: "origin",
57
+ subjectValue: c
58
+ };
59
+ if (n.agent.some((e) => e.uri in u)) return {
60
+ kind: "agent",
61
+ subjectValue: s.any(l, e.foaf("preferredURI"))?.value ?? c
62
+ };
63
+ if (n.agentGroup.some((e) => e.uri in u)) return {
64
+ kind: "agentGroup",
65
+ subjectValue: c
66
+ };
67
+ if (n.agentClass.some((e) => l.sameTerm(e))) return {
68
+ kind: "agentClass",
69
+ subjectValue: c
70
+ };
71
+ }
72
+ //#endregion
73
+ export { s as classifyAccessControlSubject };
74
+
75
+ //# sourceMappingURL=accessControlSubjects.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accessControlSubjects.esm.js","names":[],"sources":["../../src/acl/accessControlSubjects.ts"],"sourcesContent":["import { LiveStore, sym } from 'rdflib'\nimport { ns } from '../util/ns'\n\nexport type AccessControlSubjectKind = 'agent' | 'agentGroup' | 'agentClass' | 'origin'\n\nexport type AccessControlSubject = {\n kind: AccessControlSubjectKind\n subjectValue: string\n}\n\nconst ACCESS_CONTROL_SUBJECT_GROUPS = {\n agentClass: [ns.foaf('Agent'), ns.acl('AuthenticatedAgent'), ns.rdf('Resource'), ns.owl('Thing')],\n agent: [ns.vcard('WebID'), ns.vcard('Individual'), ns.foaf('Person'), ns.foaf('Agent')],\n agentGroup: [ns.vcard('Group')],\n origin: [ns.solid('AppProvider'), ns.solid('AppProviderClass')]\n} as const\n\nfunction hasKnownTypes (types: Record<string, unknown>): boolean {\n return Object.keys(types).length > 0\n}\n\nfunction isHttpUrl (value: string): boolean {\n return value.startsWith('http://') || value.startsWith('https://')\n}\n\nfunction isBareOriginUrl (value: string): boolean {\n try {\n const parsed = new URL(value)\n return (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n parsed.pathname === '/' &&\n !parsed.search &&\n !parsed.hash\n } catch (_error) {\n return false\n }\n}\n\nfunction normalizeOriginUrl (value: string): string {\n try {\n const parsed = new URL(value)\n if (\n (parsed.protocol === 'http:' || parsed.protocol === 'https:') &&\n parsed.pathname === '/' &&\n !parsed.search &&\n !parsed.hash\n ) {\n return `${parsed.protocol}//${parsed.host}`\n }\n } catch (_error) {\n // Return the original value below when parsing fails.\n }\n\n return value\n}\n\nexport async function classifyAccessControlSubject (store: LiveStore, principle: string): Promise<AccessControlSubject | undefined> {\n const subject = sym(principle)\n let types = store.findTypeURIs(subject)\n\n if (isBareOriginUrl(principle)) {\n return { kind: 'origin', subjectValue: normalizeOriginUrl(principle) }\n }\n\n if (!hasKnownTypes(types) && isHttpUrl(principle)) {\n try {\n await store.fetcher.load(subject.doc())\n } catch (error) {\n console.error(`Failed to load access target ${principle}`, error)\n }\n\n types = store.findTypeURIs(subject)\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.origin.some(term => term.uri in types)) {\n return { kind: 'origin', subjectValue: principle }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agent.some(term => term.uri in types)) {\n const preferredURI = store.any(subject, ns.foaf('preferredURI'))\n return {\n kind: 'agent',\n subjectValue: preferredURI?.value ?? principle\n }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agentGroup.some(term => term.uri in types)) {\n return { kind: 'agentGroup', subjectValue: principle }\n }\n\n if (ACCESS_CONTROL_SUBJECT_GROUPS.agentClass.some(term => subject.sameTerm(term))) {\n return { kind: 'agentClass', subjectValue: principle }\n }\n\n return undefined\n}\n"],"mappings":";;;AAUA,IAAM,IAAgC;CAClC,YAAY;EAAC,EAAG,KAAK,OAAO;EAAG,EAAG,IAAI,oBAAoB;EAAG,EAAG,IAAI,UAAU;EAAG,EAAG,IAAI,OAAO;CAAC;CAChG,OAAO;EAAC,EAAG,MAAM,OAAO;EAAG,EAAG,MAAM,YAAY;EAAG,EAAG,KAAK,QAAQ;EAAG,EAAG,KAAK,OAAO;CAAC;CACtF,YAAY,CAAC,EAAG,MAAM,OAAO,CAAC;CAC9B,QAAQ,CAAC,EAAG,MAAM,aAAa,GAAG,EAAG,MAAM,kBAAkB,CAAC;AAClE;AAEA,SAAS,EAAe,GAAyC;CAC7D,OAAO,OAAO,KAAK,CAAK,CAAC,CAAC,SAAS;AACvC;AAEA,SAAS,EAAW,GAAwB;CACxC,OAAO,EAAM,WAAW,SAAS,KAAK,EAAM,WAAW,UAAU;AACrE;AAEA,SAAS,EAAiB,GAAwB;CAC9C,IAAI;EACA,IAAM,IAAS,IAAI,IAAI,CAAK;EAC5B,QAAQ,EAAO,aAAa,WAAW,EAAO,aAAa,aACvD,EAAO,aAAa,OACpB,CAAC,EAAO,UACR,CAAC,EAAO;CAChB,QAAiB;EACb,OAAO;CACX;AACJ;AAEA,SAAS,EAAoB,GAAuB;CAChD,IAAI;EACA,IAAM,IAAS,IAAI,IAAI,CAAK;EAC5B,KACK,EAAO,aAAa,WAAW,EAAO,aAAa,aACpD,EAAO,aAAa,OACpB,CAAC,EAAO,UACR,CAAC,EAAO,MAER,OAAO,GAAG,EAAO,SAAS,IAAI,EAAO;CAE7C,QAAiB,CAEjB;CAEA,OAAO;AACX;AAEA,eAAsB,EAA8B,GAAkB,GAA8D;CAChI,IAAM,IAAU,EAAI,CAAS,GACzB,IAAQ,EAAM,aAAa,CAAO;CAEtC,IAAI,EAAgB,CAAS,GACzB,OAAO;EAAE,MAAM;EAAU,cAAc,EAAmB,CAAS;CAAE;CAGzE,IAAI,CAAC,EAAc,CAAK,KAAK,EAAU,CAAS,GAAG;EAC/C,IAAI;GACA,MAAM,EAAM,QAAQ,KAAK,EAAQ,IAAI,CAAC;EAC1C,SAAS,GAAO;GACZ,QAAQ,MAAM,gCAAgC,KAAa,CAAK;EACpE;EAEA,IAAQ,EAAM,aAAa,CAAO;CACtC;CAEA,IAAI,EAA8B,OAAO,MAAK,MAAQ,EAAK,OAAO,CAAK,GACnE,OAAO;EAAE,MAAM;EAAU,cAAc;CAAU;CAGrD,IAAI,EAA8B,MAAM,MAAK,MAAQ,EAAK,OAAO,CAAK,GAElE,OAAO;EACH,MAAM;EACN,cAHiB,EAAM,IAAI,GAAS,EAAG,KAAK,cAAc,CAG5C,CAAA,EAAc,SAAS;CACzC;CAGJ,IAAI,EAA8B,WAAW,MAAK,MAAQ,EAAK,OAAO,CAAK,GACvE,OAAO;EAAE,MAAM;EAAc,cAAc;CAAU;CAGzD,IAAI,EAA8B,WAAW,MAAK,MAAQ,EAAQ,SAAS,CAAI,CAAC,GAC5E,OAAO;EAAE,MAAM;EAAc,cAAc;CAAU;AAI7D"}
@@ -1,2 +1,2 @@
1
- const e=require("../util/ns.cjs.js");let t=require("rdflib");var n=(0,t.sym)(`http://www.iana.org/assignments/link-relations/acl`);function r(r){let i=e.ns;async function a(e){await r.fetcher.load(e);let t=r.any(e,n);if(!t)throw Error(`No ACL link discovered for ${e}`);return t.value}function o(e,t,i){let a=r.any(r.sym(e),n);return Promise.resolve().then(()=>a||s(e).catch(t=>{throw Error(`Error fetching rel=ACL header for ${e}: ${t}`)})).then(n=>{let a=c(e,t,n.uri,i);if(!r.fetcher)throw Error(`Cannot PUT this, store has no fetcher`);return r.fetcher.webOperation(`PUT`,n.uri,{data:a,contentType:`text/turtle`}).then(e=>{if(!e.ok)throw Error(`Error writing ACL text: `+e.error);return n})})}function s(e){let t=r.fetcher;if(!t)throw Error(`Cannot fetch ACL rel, store has no fetcher`);return t.load(e).then(t=>{if(!t.ok)throw Error(`fetchACLRel: While loading:`+t.error);let i=r.any(r.sym(e),n);if(!i)throw Error(`fetchACLRel: No Link rel=ACL header for `+e);return i})}function c(e,n,r,a={}){let o=a.public||[],s=(0,t.graph)(),c=(0,t.Namespace)(`http://www.w3.org/ns/auth/acl#`),l=s.sym(`${r}#a1`),u=s.sym(r),d=s.sym(e);if(s.add(l,i.rdf(`type`),c(`Authorization`),u),s.add(l,c(`accessTo`),d,u),a.defaultForNew&&s.add(l,c(`default`),d,u),s.add(l,c(`agent`),n,u),s.add(l,c(`mode`),c(`Read`),u),s.add(l,c(`mode`),c(`Write`),u),s.add(l,c(`mode`),c(`Control`),u),o.length){l=s.sym(`${r}#a2`),s.add(l,i.rdf(`type`),c(`Authorization`),u),s.add(l,c(`accessTo`),d,u),s.add(l,c(`agentClass`),i.foaf(`Agent`),u);for(let e=0;e<o.length;e++)s.add(l,c(`mode`),c(o[e]),u)}return(0,t.serialize)(u,s,r)}return{findAclDocUrl:a,setACLUserPublic:o,genACLText:c}}exports.ACL_LINK=n,exports.createAclLogic=r;
1
+ const e=require("../util/ns.cjs.js"),t=require("./accessControlSubjects.cjs.js");let n=require("rdflib"),r=require("@dokieli/web-access-control");var i=[`Owner`,`Editor`,`No Access`,`Viewer`,`Poster`,`Submitter`],a=(0,n.sym)(`http://www.iana.org/assignments/link-relations/acl`);function o(i){let o=e.ns,s=[{label:`Owner`,modes:[`Read`,`Write`,`Control`]},{label:`Editor`,modes:[`Read`,`Write`]},{label:`Poster`,modes:[`Append`,`Read`]},{label:`Submitter`,modes:[`Append`]},{label:`Viewer`,modes:[`Read`]},{label:`No Access`,modes:[]}];function c(e){let t=new Set(e);return s.find(e=>e.label!==`No Access`&&e.modes.every(e=>t.has(e)))?.label??`No Access`}function l(e){return[...s.find(t=>t.label===e)?.modes??[]]}function u(){let e=i.fetcher,t=e?._fetch??e?.fetch;if(!t)throw Error(`Cannot find effective ACL, store has no fetcher`);return t.bind(e)}async function d(e){await i.fetcher.load(e);let t=i.any(e,a);if(!t)throw Error(`No ACL link discovered for ${e}`);return t.value}async function f(e){let t=typeof e==`string`?e:e.value;return(0,r.findEffectiveACL)(t,{fetch:u()})}async function p(e){return(await f(e)).authorizations}async function m(e,t,n){let i=await f(e);return(0,r.planGrant)(i,t,n)}async function h(e,t){let n=await f(e);return(0,r.planRevoke)(n,t)}async function g(e,t){let n=await f(e);return(0,r.planPublicRead)(n,t)}async function _(e){return(0,r.applyPlan)(e,{fetch:u()})}async function v(e){return t.classifyAccessControlSubject(i,e)}function y(e,t,n){let r=i.any(i.sym(e),a);return Promise.resolve().then(()=>r||b(e).catch(t=>{throw Error(`Error fetching rel=ACL header for ${e}: ${t}`)})).then(r=>{let a=x(e,t,r.uri,n);if(!i.fetcher)throw Error(`Cannot PUT this, store has no fetcher`);return i.fetcher.webOperation(`PUT`,r.uri,{data:a,contentType:`text/turtle`}).then(e=>{if(!e.ok)throw Error(`Error writing ACL text: `+e.error);return r})})}function b(e){let t=i.fetcher;if(!t)throw Error(`Cannot fetch ACL rel, store has no fetcher`);return t.load(e).then(t=>{if(!t.ok)throw Error(`fetchACLRel: While loading:`+t.error);let n=i.any(i.sym(e),a);if(!n)throw Error(`fetchACLRel: No Link rel=ACL header for `+e);return n})}function x(e,t,r,i={}){let a=i.public||[],s=(0,n.graph)(),c=(0,n.Namespace)(`http://www.w3.org/ns/auth/acl#`),l=s.sym(`${r}#a1`),u=s.sym(r),d=s.sym(e);if(s.add(l,o.rdf(`type`),c(`Authorization`),u),s.add(l,c(`accessTo`),d,u),i.defaultForNew&&s.add(l,c(`default`),d,u),s.add(l,c(`agent`),t,u),s.add(l,c(`mode`),c(`Read`),u),s.add(l,c(`mode`),c(`Write`),u),s.add(l,c(`mode`),c(`Control`),u),a.length){l=s.sym(`${r}#a2`),s.add(l,o.rdf(`type`),c(`Authorization`),u),s.add(l,c(`accessTo`),d,u),s.add(l,c(`agentClass`),o.foaf(`Agent`),u);for(let e=0;e<a.length;e++)s.add(l,c(`mode`),c(a[e]),u)}return(0,n.serialize)(u,s,r)}return{findAclDocUrl:d,findEffectiveAcl:f,findAccessGrants:p,roleFromModes:c,modesFromRole:l,planGrant:m,planRevoke:h,planPublicRead:g,applyPlan:_,classifyAccessControlSubject:v,setACLUserPublic:y,genACLText:x}}exports.ACCESS_ROLES=i,exports.ACL_LINK=a,exports.createAclLogic=o;
2
2
  //# sourceMappingURL=aclLogic.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aclLogic.cjs.js","names":[],"sources":["../../src/acl/aclLogic.ts"],"sourcesContent":["import { graph, NamedNode, Namespace, serialize, sym } from 'rdflib'\nimport { AclLogic } from '../types'\nimport { ns as namespace } from '../util/ns'\n\n\nexport const ACL_LINK = sym(\n 'http://www.iana.org/assignments/link-relations/acl'\n)\n\nexport function createAclLogic(store): AclLogic {\n\n const ns = namespace\n \n async function findAclDocUrl(url: NamedNode) {\n await store.fetcher.load(url)\n const docNode = store.any(url, ACL_LINK)\n if (!docNode) {\n throw new Error(`No ACL link discovered for ${url}`)\n }\n return docNode.value\n }\n /**\n * Simple Access Control\n *\n * This function sets up a simple default ACL for a resource, with\n * RWC for the owner, and a specified access (default none) for the public.\n * In all cases owner has read write control.\n * Parameter lists modes allowed to public\n *\n * @param options\n * @param options.public eg ['Read', 'Write']\n *\n * @returns Resolves with aclDoc uri on successful write\n */\n function setACLUserPublic ( \n docURI: string,\n me: NamedNode,\n options: {\n defaultForNew?: boolean,\n public?: []\n }\n ): Promise<NamedNode> {\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n return Promise.resolve()\n .then(() => {\n if (aclDoc) {\n return aclDoc as NamedNode\n }\n\n return fetchACLRel(docURI).catch(err => {\n throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)\n })\n })\n .then(aclDoc => {\n const aclText = genACLText(docURI, me, aclDoc.uri, options)\n if (!store.fetcher) {\n throw new Error('Cannot PUT this, store has no fetcher')\n }\n return store.fetcher\n .webOperation('PUT', aclDoc.uri, {\n data: aclText,\n contentType: 'text/turtle'\n })\n .then(result => {\n if (!result.ok) {\n throw new Error('Error writing ACL text: ' + result.error)\n }\n\n return aclDoc\n })\n })\n }\n\n /**\n * @param docURI\n * @returns\n */\n function fetchACLRel (docURI: string): Promise<NamedNode> {\n const fetcher = store.fetcher\n if (!fetcher) {\n throw new Error('Cannot fetch ACL rel, store has no fetcher')\n }\n\n return fetcher.load(docURI).then(result => {\n if (!result.ok) {\n throw new Error('fetchACLRel: While loading:' + (result as any).error)\n }\n\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n if (!aclDoc) {\n throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)\n }\n\n return aclDoc as NamedNode\n })\n }\n\n /**\n * @param docURI\n * @param me\n * @param aclURI\n * @param options\n *\n * @returns Serialized ACL\n */\n function genACLText (\n docURI: string,\n me: NamedNode,\n aclURI: string,\n options: {\n defaultForNew?: boolean,\n public?: []\n } = {}\n ): string | undefined {\n const optPublic = options.public || []\n const g = graph()\n const auth = Namespace('http://www.w3.org/ns/auth/acl#')\n let a = g.sym(`${aclURI}#a1`)\n const acl = g.sym(aclURI)\n const doc = g.sym(docURI)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n if (options.defaultForNew) {\n g.add(a, auth('default'), doc, acl)\n }\n g.add(a, auth('agent'), me, acl)\n g.add(a, auth('mode'), auth('Read'), acl)\n g.add(a, auth('mode'), auth('Write'), acl)\n g.add(a, auth('mode'), auth('Control'), acl)\n\n if (optPublic.length) {\n a = g.sym(`${aclURI}#a2`)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)\n for (let p = 0; p < optPublic.length; p++) {\n g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc\n }\n }\n return serialize(acl, g, aclURI)\n }\n return {\n findAclDocUrl,\n setACLUserPublic,\n genACLText\n }\n}"],"mappings":"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"}
1
+ {"version":3,"file":"aclLogic.cjs.js","names":[],"sources":["../../src/acl/aclLogic.ts"],"sourcesContent":["import { applyPlan as applyAuthorizationPlan, findEffectiveACL, planGrant as planAuthorizationGrant, planPublicRead as planAuthorizationPublicRead, planRevoke as planAuthorizationRevoke, type AccessMode, type AccessSubject, type ACLContext, type Authorization, type PatchPlan } from '@dokieli/web-access-control'\nimport { graph, NamedNode, Namespace, serialize, sym } from 'rdflib'\nimport type { AclLogic } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport * as accessControlSubjects from './accessControlSubjects'\n\n// Will remove the below comment when i'm done with the manage access work\n// Helpers available from @dokieli/web-access-control:\n// - Discovery: findEffectiveACL, parentContainer\n// - ACL context and parsing: buildACLContext, authorizationsFromDataset, parseTurtle\n// - Query helpers: agentsWithMode, hasControl, isPublic, modesFor, subjectsWithMode\n// - Plan helpers: planContainerACL, planGrant, planOwnerControl, planPublicRead, planRevoke\n// - Serialization and application: serializeTerm, toN3Patch, toSparqlUpdate, toTurtle, applyPlan, negotiatePatchContentType\n// - Link and allow parsing: allows, parseWacAllow, linkTargets, parseLinkHeader\n// - Terms and constants: ACCESS_MODES, ACL, Authenticated, FOAF, modeFromIRI, modeIRI, namedNode, Public, quad, RDF_TYPE, variable\n\nexport const ACCESS_ROLES = ['Owner', 'Editor', 'No Access', 'Viewer', 'Poster', 'Submitter'] as const\n\nexport type AccessRole = typeof ACCESS_ROLES[number]\n\nexport const ACL_LINK = sym(\n 'http://www.iana.org/assignments/link-relations/acl'\n)\n\nexport function createAclLogic(store): AclLogic {\n\n const ns = namespace\n const ACCESS_ROLE_RULES: Array<{ label: AccessRole, modes: AccessMode[] }> = [\n { label: 'Owner', modes: ['Read', 'Write', 'Control'] },\n { label: 'Editor', modes: ['Read', 'Write'] },\n { label: 'Poster', modes: ['Append', 'Read'] },\n { label: 'Submitter', modes: ['Append'] },\n { label: 'Viewer', modes: ['Read'] },\n { label: 'No Access', modes: [] }\n ]\n\n function roleFromModes (modes: Iterable<AccessMode>): AccessRole {\n const modeSet = new Set(modes)\n const matchingRule = ACCESS_ROLE_RULES.find(rule => rule.label !== 'No Access' && rule.modes.every(mode => modeSet.has(mode)))\n\n return matchingRule?.label ?? 'No Access'\n }\n\n function modesFromRole (role: AccessRole): AccessMode[] {\n return [...(ACCESS_ROLE_RULES.find(rule => rule.label === role)?.modes ?? [])]\n }\n\n function getFetch() {\n const fetcher = store.fetcher as {\n _fetch?: (url: string, init?: RequestInit) => Promise<Response>\n fetch?: (url: string, init?: RequestInit) => Promise<Response>\n } | undefined\n const fetch = fetcher?._fetch ?? fetcher?.fetch\n if (!fetch) {\n throw new Error('Cannot find effective ACL, store has no fetcher')\n }\n return fetch.bind(fetcher)\n }\n \n async function findAclDocUrl(url: NamedNode) {\n await store.fetcher.load(url)\n const docNode = store.any(url, ACL_LINK)\n if (!docNode) {\n throw new Error(`No ACL link discovered for ${url}`)\n }\n return docNode.value\n }\n\n async function findEffectiveAcl(resourceURL: string | NamedNode): Promise<ACLContext> {\n const url = typeof resourceURL === 'string' ? resourceURL : resourceURL.value\n return findEffectiveACL(url, { fetch: getFetch() })\n }\n\n async function findAccessGrants(resourceURL: string | NamedNode): Promise<Authorization[]> {\n const context = await findEffectiveAcl(resourceURL)\n return context.authorizations\n }\n\n async function planGrant(resourceURL: string | NamedNode, subject: AccessSubject, modes: AccessMode[]): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationGrant(context, subject, modes)\n }\n\n async function planRevoke(resourceURL: string | NamedNode, subject: AccessSubject): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationRevoke(context, subject)\n }\n\n async function planPublicRead(resourceURL: string | NamedNode, enabled: boolean): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationPublicRead(context, enabled)\n }\n\n async function applyPlan(plan: PatchPlan): Promise<Response> {\n return applyAuthorizationPlan(plan, { fetch: getFetch() })\n }\n\n async function classifyAccessControlSubject(principle: string) {\n return accessControlSubjects.classifyAccessControlSubject(store, principle)\n }\n /**\n * Simple Access Control\n *\n * This function sets up a simple default ACL for a resource, with\n * RWC for the owner, and a specified access (default none) for the public.\n * In all cases owner has read write control.\n * Parameter lists modes allowed to public\n *\n * @param options\n * @param options.public eg ['Read', 'Write']\n *\n * @returns Resolves with aclDoc uri on successful write\n */\n function setACLUserPublic ( \n docURI: string,\n me: NamedNode,\n options: {\n defaultForNew?: boolean,\n public?: []\n }\n ): Promise<NamedNode> {\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n return Promise.resolve()\n .then(() => {\n if (aclDoc) {\n return aclDoc as NamedNode\n }\n\n return fetchACLRel(docURI).catch(err => {\n throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)\n })\n })\n .then(aclDoc => {\n const aclText = genACLText(docURI, me, aclDoc.uri, options)\n if (!store.fetcher) {\n throw new Error('Cannot PUT this, store has no fetcher')\n }\n return store.fetcher\n .webOperation('PUT', aclDoc.uri, {\n data: aclText,\n contentType: 'text/turtle'\n })\n .then(result => {\n if (!result.ok) {\n throw new Error('Error writing ACL text: ' + result.error)\n }\n\n return aclDoc\n })\n })\n }\n\n /**\n * @param docURI\n * @returns\n */\n function fetchACLRel (docURI: string): Promise<NamedNode> {\n const fetcher = store.fetcher\n if (!fetcher) {\n throw new Error('Cannot fetch ACL rel, store has no fetcher')\n }\n\n return fetcher.load(docURI).then(result => {\n if (!result.ok) {\n throw new Error('fetchACLRel: While loading:' + (result as any).error)\n }\n\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n if (!aclDoc) {\n throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)\n }\n\n return aclDoc as NamedNode\n })\n }\n\n /**\n * @param docURI\n * @param me\n * @param aclURI\n * @param options\n *\n * @returns Serialized ACL\n */\n function genACLText (\n docURI: string,\n me: NamedNode,\n aclURI: string,\n options: {\n defaultForNew?: boolean,\n public?: []\n } = {}\n ): string | undefined {\n const optPublic = options.public || []\n const g = graph()\n const auth = Namespace('http://www.w3.org/ns/auth/acl#')\n let a = g.sym(`${aclURI}#a1`)\n const acl = g.sym(aclURI)\n const doc = g.sym(docURI)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n if (options.defaultForNew) {\n g.add(a, auth('default'), doc, acl)\n }\n g.add(a, auth('agent'), me, acl)\n g.add(a, auth('mode'), auth('Read'), acl)\n g.add(a, auth('mode'), auth('Write'), acl)\n g.add(a, auth('mode'), auth('Control'), acl)\n\n if (optPublic.length) {\n a = g.sym(`${aclURI}#a2`)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)\n for (let p = 0; p < optPublic.length; p++) {\n g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc\n }\n }\n return serialize(acl, g, aclURI)\n }\n return {\n findAclDocUrl,\n findEffectiveAcl,\n findAccessGrants,\n roleFromModes,\n modesFromRole,\n planGrant,\n planRevoke,\n planPublicRead,\n applyPlan,\n classifyAccessControlSubject,\n setACLUserPublic,\n genACLText\n }\n}"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { NamedNode } from 'rdflib';
2
+ import type { AclLogic } from '../types';
3
+ export declare const ACCESS_ROLES: readonly ["Owner", "Editor", "No Access", "Viewer", "Poster", "Submitter"];
4
+ export type AccessRole = typeof ACCESS_ROLES[number];
5
+ export declare const ACL_LINK: NamedNode;
6
+ export declare function createAclLogic(store: any): AclLogic;
7
+ //# sourceMappingURL=aclLogic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aclLogic.d.ts","sourceRoot":"","sources":["../../src/acl/aclLogic.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,SAAS,EAA6B,MAAM,QAAQ,CAAA;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAcxC,eAAO,MAAM,YAAY,4EAA6E,CAAA;AAEtG,MAAM,MAAM,UAAU,GAAG,OAAO,YAAY,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,QAAQ,WAEpB,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,KAAA,GAAG,QAAQ,CA0N9C"}
@@ -1,24 +1,99 @@
1
1
  import { ns as e } from "../util/ns.esm.js";
2
- import { Namespace as t, graph as n, serialize as r, sym as i } from "rdflib";
2
+ import { classifyAccessControlSubject as t } from "./accessControlSubjects.esm.js";
3
+ import { Namespace as n, graph as r, serialize as i, sym as a } from "rdflib";
4
+ import { applyPlan as o, findEffectiveACL as s, planGrant as c, planPublicRead as l, planRevoke as u } from "@dokieli/web-access-control";
3
5
  //#region src/acl/aclLogic.ts
4
- var a = i("http://www.iana.org/assignments/link-relations/acl");
5
- function o(i) {
6
- let o = e;
7
- async function s(e) {
8
- await i.fetcher.load(e);
9
- let t = i.any(e, a);
6
+ var d = [
7
+ "Owner",
8
+ "Editor",
9
+ "No Access",
10
+ "Viewer",
11
+ "Poster",
12
+ "Submitter"
13
+ ], f = a("http://www.iana.org/assignments/link-relations/acl");
14
+ function p(a) {
15
+ let d = e, p = [
16
+ {
17
+ label: "Owner",
18
+ modes: [
19
+ "Read",
20
+ "Write",
21
+ "Control"
22
+ ]
23
+ },
24
+ {
25
+ label: "Editor",
26
+ modes: ["Read", "Write"]
27
+ },
28
+ {
29
+ label: "Poster",
30
+ modes: ["Append", "Read"]
31
+ },
32
+ {
33
+ label: "Submitter",
34
+ modes: ["Append"]
35
+ },
36
+ {
37
+ label: "Viewer",
38
+ modes: ["Read"]
39
+ },
40
+ {
41
+ label: "No Access",
42
+ modes: []
43
+ }
44
+ ];
45
+ function m(e) {
46
+ let t = new Set(e);
47
+ return p.find((e) => e.label !== "No Access" && e.modes.every((e) => t.has(e)))?.label ?? "No Access";
48
+ }
49
+ function h(e) {
50
+ return [...p.find((t) => t.label === e)?.modes ?? []];
51
+ }
52
+ function g() {
53
+ let e = a.fetcher, t = e?._fetch ?? e?.fetch;
54
+ if (!t) throw Error("Cannot find effective ACL, store has no fetcher");
55
+ return t.bind(e);
56
+ }
57
+ async function _(e) {
58
+ await a.fetcher.load(e);
59
+ let t = a.any(e, f);
10
60
  if (!t) throw Error(`No ACL link discovered for ${e}`);
11
61
  return t.value;
12
62
  }
13
- function c(e, t, n) {
14
- let r = i.any(i.sym(e), a);
15
- return Promise.resolve().then(() => r || l(e).catch((t) => {
63
+ async function v(e) {
64
+ let t = typeof e == "string" ? e : e.value;
65
+ return s(t, { fetch: g() });
66
+ }
67
+ async function y(e) {
68
+ return (await v(e)).authorizations;
69
+ }
70
+ async function b(e, t, n) {
71
+ let r = await v(e);
72
+ return c(r, t, n);
73
+ }
74
+ async function x(e, t) {
75
+ let n = await v(e);
76
+ return u(n, t);
77
+ }
78
+ async function S(e, t) {
79
+ let n = await v(e);
80
+ return l(n, t);
81
+ }
82
+ async function C(e) {
83
+ return o(e, { fetch: g() });
84
+ }
85
+ async function w(e) {
86
+ return t(a, e);
87
+ }
88
+ function T(e, t, n) {
89
+ let r = a.any(a.sym(e), f);
90
+ return Promise.resolve().then(() => r || E(e).catch((t) => {
16
91
  throw Error(`Error fetching rel=ACL header for ${e}: ${t}`);
17
92
  })).then((r) => {
18
- let a = u(e, t, r.uri, n);
19
- if (!i.fetcher) throw Error("Cannot PUT this, store has no fetcher");
20
- return i.fetcher.webOperation("PUT", r.uri, {
21
- data: a,
93
+ let i = D(e, t, r.uri, n);
94
+ if (!a.fetcher) throw Error("Cannot PUT this, store has no fetcher");
95
+ return a.fetcher.webOperation("PUT", r.uri, {
96
+ data: i,
22
97
  contentType: "text/turtle"
23
98
  }).then((e) => {
24
99
  if (!e.ok) throw Error("Error writing ACL text: " + e.error);
@@ -26,31 +101,40 @@ function o(i) {
26
101
  });
27
102
  });
28
103
  }
29
- function l(e) {
30
- let t = i.fetcher;
104
+ function E(e) {
105
+ let t = a.fetcher;
31
106
  if (!t) throw Error("Cannot fetch ACL rel, store has no fetcher");
32
107
  return t.load(e).then((t) => {
33
108
  if (!t.ok) throw Error("fetchACLRel: While loading:" + t.error);
34
- let n = i.any(i.sym(e), a);
109
+ let n = a.any(a.sym(e), f);
35
110
  if (!n) throw Error("fetchACLRel: No Link rel=ACL header for " + e);
36
111
  return n;
37
112
  });
38
113
  }
39
- function u(e, i, a, s = {}) {
40
- let c = s.public || [], l = n(), u = t("http://www.w3.org/ns/auth/acl#"), d = l.sym(`${a}#a1`), f = l.sym(a), p = l.sym(e);
41
- if (l.add(d, o.rdf("type"), u("Authorization"), f), l.add(d, u("accessTo"), p, f), s.defaultForNew && l.add(d, u("default"), p, f), l.add(d, u("agent"), i, f), l.add(d, u("mode"), u("Read"), f), l.add(d, u("mode"), u("Write"), f), l.add(d, u("mode"), u("Control"), f), c.length) {
42
- d = l.sym(`${a}#a2`), l.add(d, o.rdf("type"), u("Authorization"), f), l.add(d, u("accessTo"), p, f), l.add(d, u("agentClass"), o.foaf("Agent"), f);
43
- for (let e = 0; e < c.length; e++) l.add(d, u("mode"), u(c[e]), f);
114
+ function D(e, t, a, o = {}) {
115
+ let s = o.public || [], c = r(), l = n("http://www.w3.org/ns/auth/acl#"), u = c.sym(`${a}#a1`), f = c.sym(a), p = c.sym(e);
116
+ if (c.add(u, d.rdf("type"), l("Authorization"), f), c.add(u, l("accessTo"), p, f), o.defaultForNew && c.add(u, l("default"), p, f), c.add(u, l("agent"), t, f), c.add(u, l("mode"), l("Read"), f), c.add(u, l("mode"), l("Write"), f), c.add(u, l("mode"), l("Control"), f), s.length) {
117
+ u = c.sym(`${a}#a2`), c.add(u, d.rdf("type"), l("Authorization"), f), c.add(u, l("accessTo"), p, f), c.add(u, l("agentClass"), d.foaf("Agent"), f);
118
+ for (let e = 0; e < s.length; e++) c.add(u, l("mode"), l(s[e]), f);
44
119
  }
45
- return r(f, l, a);
120
+ return i(f, c, a);
46
121
  }
47
122
  return {
48
- findAclDocUrl: s,
49
- setACLUserPublic: c,
50
- genACLText: u
123
+ findAclDocUrl: _,
124
+ findEffectiveAcl: v,
125
+ findAccessGrants: y,
126
+ roleFromModes: m,
127
+ modesFromRole: h,
128
+ planGrant: b,
129
+ planRevoke: x,
130
+ planPublicRead: S,
131
+ applyPlan: C,
132
+ classifyAccessControlSubject: w,
133
+ setACLUserPublic: T,
134
+ genACLText: D
51
135
  };
52
136
  }
53
137
  //#endregion
54
- export { a as ACL_LINK, o as createAclLogic };
138
+ export { d as ACCESS_ROLES, f as ACL_LINK, p as createAclLogic };
55
139
 
56
140
  //# sourceMappingURL=aclLogic.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"aclLogic.esm.js","names":[],"sources":["../../src/acl/aclLogic.ts"],"sourcesContent":["import { graph, NamedNode, Namespace, serialize, sym } from 'rdflib'\nimport { AclLogic } from '../types'\nimport { ns as namespace } from '../util/ns'\n\n\nexport const ACL_LINK = sym(\n 'http://www.iana.org/assignments/link-relations/acl'\n)\n\nexport function createAclLogic(store): AclLogic {\n\n const ns = namespace\n \n async function findAclDocUrl(url: NamedNode) {\n await store.fetcher.load(url)\n const docNode = store.any(url, ACL_LINK)\n if (!docNode) {\n throw new Error(`No ACL link discovered for ${url}`)\n }\n return docNode.value\n }\n /**\n * Simple Access Control\n *\n * This function sets up a simple default ACL for a resource, with\n * RWC for the owner, and a specified access (default none) for the public.\n * In all cases owner has read write control.\n * Parameter lists modes allowed to public\n *\n * @param options\n * @param options.public eg ['Read', 'Write']\n *\n * @returns Resolves with aclDoc uri on successful write\n */\n function setACLUserPublic ( \n docURI: string,\n me: NamedNode,\n options: {\n defaultForNew?: boolean,\n public?: []\n }\n ): Promise<NamedNode> {\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n return Promise.resolve()\n .then(() => {\n if (aclDoc) {\n return aclDoc as NamedNode\n }\n\n return fetchACLRel(docURI).catch(err => {\n throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)\n })\n })\n .then(aclDoc => {\n const aclText = genACLText(docURI, me, aclDoc.uri, options)\n if (!store.fetcher) {\n throw new Error('Cannot PUT this, store has no fetcher')\n }\n return store.fetcher\n .webOperation('PUT', aclDoc.uri, {\n data: aclText,\n contentType: 'text/turtle'\n })\n .then(result => {\n if (!result.ok) {\n throw new Error('Error writing ACL text: ' + result.error)\n }\n\n return aclDoc\n })\n })\n }\n\n /**\n * @param docURI\n * @returns\n */\n function fetchACLRel (docURI: string): Promise<NamedNode> {\n const fetcher = store.fetcher\n if (!fetcher) {\n throw new Error('Cannot fetch ACL rel, store has no fetcher')\n }\n\n return fetcher.load(docURI).then(result => {\n if (!result.ok) {\n throw new Error('fetchACLRel: While loading:' + (result as any).error)\n }\n\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n if (!aclDoc) {\n throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)\n }\n\n return aclDoc as NamedNode\n })\n }\n\n /**\n * @param docURI\n * @param me\n * @param aclURI\n * @param options\n *\n * @returns Serialized ACL\n */\n function genACLText (\n docURI: string,\n me: NamedNode,\n aclURI: string,\n options: {\n defaultForNew?: boolean,\n public?: []\n } = {}\n ): string | undefined {\n const optPublic = options.public || []\n const g = graph()\n const auth = Namespace('http://www.w3.org/ns/auth/acl#')\n let a = g.sym(`${aclURI}#a1`)\n const acl = g.sym(aclURI)\n const doc = g.sym(docURI)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n if (options.defaultForNew) {\n g.add(a, auth('default'), doc, acl)\n }\n g.add(a, auth('agent'), me, acl)\n g.add(a, auth('mode'), auth('Read'), acl)\n g.add(a, auth('mode'), auth('Write'), acl)\n g.add(a, auth('mode'), auth('Control'), acl)\n\n if (optPublic.length) {\n a = g.sym(`${aclURI}#a2`)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)\n for (let p = 0; p < optPublic.length; p++) {\n g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc\n }\n }\n return serialize(acl, g, aclURI)\n }\n return {\n findAclDocUrl,\n setACLUserPublic,\n genACLText\n }\n}"],"mappings":"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"}
1
+ {"version":3,"file":"aclLogic.esm.js","names":[],"sources":["../../src/acl/aclLogic.ts"],"sourcesContent":["import { applyPlan as applyAuthorizationPlan, findEffectiveACL, planGrant as planAuthorizationGrant, planPublicRead as planAuthorizationPublicRead, planRevoke as planAuthorizationRevoke, type AccessMode, type AccessSubject, type ACLContext, type Authorization, type PatchPlan } from '@dokieli/web-access-control'\nimport { graph, NamedNode, Namespace, serialize, sym } from 'rdflib'\nimport type { AclLogic } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport * as accessControlSubjects from './accessControlSubjects'\n\n// Will remove the below comment when i'm done with the manage access work\n// Helpers available from @dokieli/web-access-control:\n// - Discovery: findEffectiveACL, parentContainer\n// - ACL context and parsing: buildACLContext, authorizationsFromDataset, parseTurtle\n// - Query helpers: agentsWithMode, hasControl, isPublic, modesFor, subjectsWithMode\n// - Plan helpers: planContainerACL, planGrant, planOwnerControl, planPublicRead, planRevoke\n// - Serialization and application: serializeTerm, toN3Patch, toSparqlUpdate, toTurtle, applyPlan, negotiatePatchContentType\n// - Link and allow parsing: allows, parseWacAllow, linkTargets, parseLinkHeader\n// - Terms and constants: ACCESS_MODES, ACL, Authenticated, FOAF, modeFromIRI, modeIRI, namedNode, Public, quad, RDF_TYPE, variable\n\nexport const ACCESS_ROLES = ['Owner', 'Editor', 'No Access', 'Viewer', 'Poster', 'Submitter'] as const\n\nexport type AccessRole = typeof ACCESS_ROLES[number]\n\nexport const ACL_LINK = sym(\n 'http://www.iana.org/assignments/link-relations/acl'\n)\n\nexport function createAclLogic(store): AclLogic {\n\n const ns = namespace\n const ACCESS_ROLE_RULES: Array<{ label: AccessRole, modes: AccessMode[] }> = [\n { label: 'Owner', modes: ['Read', 'Write', 'Control'] },\n { label: 'Editor', modes: ['Read', 'Write'] },\n { label: 'Poster', modes: ['Append', 'Read'] },\n { label: 'Submitter', modes: ['Append'] },\n { label: 'Viewer', modes: ['Read'] },\n { label: 'No Access', modes: [] }\n ]\n\n function roleFromModes (modes: Iterable<AccessMode>): AccessRole {\n const modeSet = new Set(modes)\n const matchingRule = ACCESS_ROLE_RULES.find(rule => rule.label !== 'No Access' && rule.modes.every(mode => modeSet.has(mode)))\n\n return matchingRule?.label ?? 'No Access'\n }\n\n function modesFromRole (role: AccessRole): AccessMode[] {\n return [...(ACCESS_ROLE_RULES.find(rule => rule.label === role)?.modes ?? [])]\n }\n\n function getFetch() {\n const fetcher = store.fetcher as {\n _fetch?: (url: string, init?: RequestInit) => Promise<Response>\n fetch?: (url: string, init?: RequestInit) => Promise<Response>\n } | undefined\n const fetch = fetcher?._fetch ?? fetcher?.fetch\n if (!fetch) {\n throw new Error('Cannot find effective ACL, store has no fetcher')\n }\n return fetch.bind(fetcher)\n }\n \n async function findAclDocUrl(url: NamedNode) {\n await store.fetcher.load(url)\n const docNode = store.any(url, ACL_LINK)\n if (!docNode) {\n throw new Error(`No ACL link discovered for ${url}`)\n }\n return docNode.value\n }\n\n async function findEffectiveAcl(resourceURL: string | NamedNode): Promise<ACLContext> {\n const url = typeof resourceURL === 'string' ? resourceURL : resourceURL.value\n return findEffectiveACL(url, { fetch: getFetch() })\n }\n\n async function findAccessGrants(resourceURL: string | NamedNode): Promise<Authorization[]> {\n const context = await findEffectiveAcl(resourceURL)\n return context.authorizations\n }\n\n async function planGrant(resourceURL: string | NamedNode, subject: AccessSubject, modes: AccessMode[]): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationGrant(context, subject, modes)\n }\n\n async function planRevoke(resourceURL: string | NamedNode, subject: AccessSubject): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationRevoke(context, subject)\n }\n\n async function planPublicRead(resourceURL: string | NamedNode, enabled: boolean): Promise<PatchPlan> {\n const context = await findEffectiveAcl(resourceURL)\n return planAuthorizationPublicRead(context, enabled)\n }\n\n async function applyPlan(plan: PatchPlan): Promise<Response> {\n return applyAuthorizationPlan(plan, { fetch: getFetch() })\n }\n\n async function classifyAccessControlSubject(principle: string) {\n return accessControlSubjects.classifyAccessControlSubject(store, principle)\n }\n /**\n * Simple Access Control\n *\n * This function sets up a simple default ACL for a resource, with\n * RWC for the owner, and a specified access (default none) for the public.\n * In all cases owner has read write control.\n * Parameter lists modes allowed to public\n *\n * @param options\n * @param options.public eg ['Read', 'Write']\n *\n * @returns Resolves with aclDoc uri on successful write\n */\n function setACLUserPublic ( \n docURI: string,\n me: NamedNode,\n options: {\n defaultForNew?: boolean,\n public?: []\n }\n ): Promise<NamedNode> {\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n return Promise.resolve()\n .then(() => {\n if (aclDoc) {\n return aclDoc as NamedNode\n }\n\n return fetchACLRel(docURI).catch(err => {\n throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)\n })\n })\n .then(aclDoc => {\n const aclText = genACLText(docURI, me, aclDoc.uri, options)\n if (!store.fetcher) {\n throw new Error('Cannot PUT this, store has no fetcher')\n }\n return store.fetcher\n .webOperation('PUT', aclDoc.uri, {\n data: aclText,\n contentType: 'text/turtle'\n })\n .then(result => {\n if (!result.ok) {\n throw new Error('Error writing ACL text: ' + result.error)\n }\n\n return aclDoc\n })\n })\n }\n\n /**\n * @param docURI\n * @returns\n */\n function fetchACLRel (docURI: string): Promise<NamedNode> {\n const fetcher = store.fetcher\n if (!fetcher) {\n throw new Error('Cannot fetch ACL rel, store has no fetcher')\n }\n\n return fetcher.load(docURI).then(result => {\n if (!result.ok) {\n throw new Error('fetchACLRel: While loading:' + (result as any).error)\n }\n\n const aclDoc = store.any(\n store.sym(docURI),\n ACL_LINK\n )\n\n if (!aclDoc) {\n throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)\n }\n\n return aclDoc as NamedNode\n })\n }\n\n /**\n * @param docURI\n * @param me\n * @param aclURI\n * @param options\n *\n * @returns Serialized ACL\n */\n function genACLText (\n docURI: string,\n me: NamedNode,\n aclURI: string,\n options: {\n defaultForNew?: boolean,\n public?: []\n } = {}\n ): string | undefined {\n const optPublic = options.public || []\n const g = graph()\n const auth = Namespace('http://www.w3.org/ns/auth/acl#')\n let a = g.sym(`${aclURI}#a1`)\n const acl = g.sym(aclURI)\n const doc = g.sym(docURI)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n if (options.defaultForNew) {\n g.add(a, auth('default'), doc, acl)\n }\n g.add(a, auth('agent'), me, acl)\n g.add(a, auth('mode'), auth('Read'), acl)\n g.add(a, auth('mode'), auth('Write'), acl)\n g.add(a, auth('mode'), auth('Control'), acl)\n\n if (optPublic.length) {\n a = g.sym(`${aclURI}#a2`)\n g.add(a, ns.rdf('type'), auth('Authorization'), acl)\n g.add(a, auth('accessTo'), doc, acl)\n g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)\n for (let p = 0; p < optPublic.length; p++) {\n g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc\n }\n }\n return serialize(acl, g, aclURI)\n }\n return {\n findAclDocUrl,\n findEffectiveAcl,\n findAccessGrants,\n roleFromModes,\n modesFromRole,\n planGrant,\n planRevoke,\n planPublicRead,\n applyPlan,\n classifyAccessControlSubject,\n setACLUserPublic,\n genACLText\n }\n}"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"authSession.cjs.js","names":[],"sources":["../../src/authSession/authSession.ts"],"sourcesContent":["/**\n * Auth session wiring.\n *\n * Takes the raw OIDC session from session.ts and layers on:\n * - Login compatibility shim (normalises legacy call-site signatures\n * and resolves the canonical issuer)\n * - SessionEvents shim (legacy EventEmitter-style API)\n * - Logout listener (emits 'logout' on session deactivation)\n *\n * Exports the fully assembled authSession.\n */\n\nimport type { Session as OidcSession } from '@uvdsl/solid-oidc-client-browser/core'\nimport { _session } from './session'\nimport { resolveIssuerForLogin } from './issuer'\nimport { SessionEvents } from './events'\nimport { legacySessionInfo, restoreSession, subscribeIdentity, type SessionLike } from './identityState'\n\ntype SessionCompatibilityShape = {\n webId?: string\n isActive?: boolean\n info?: {\n webId?: string\n isLoggedIn?: boolean\n }\n fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n authFetch?: (input: string | URL | Request, init?: RequestInit, dpopPayload?: any) => Promise<Response>\n}\n\ntype LoginOptionsLegacy = {\n oidcIssuer?: string\n idp?: string\n issuer?: string\n redirectUrl?: string\n redirect_uri?: string\n redirectUri?: string\n}\n\ntype LoginCompat = {\n (issuer: string, redirectUrl: string): Promise<unknown>\n (options: LoginOptionsLegacy): Promise<unknown>\n}\n\nexport type SessionWithLegacyEvents = Omit<OidcSession, 'login'> & SessionCompatibilityShape & {\n login: LoginCompat\n events: SessionEvents\n}\n\n// ---------------------------------------------------------------------------\n// Login compatibility shim\n// ---------------------------------------------------------------------------\n// Wraps _session.login() so that call sites with different calling\n// conventions all work. The underlying session expects:\n// login(issuer: string, redirectUrl: string)\n//\n// idpOrOptions can be:\n// - a string (issuer URL) — passed through with less resolution\n// - an options object with any of these field-name variants:\n// issuer: oidcIssuer | idp | issuer\n// redirect: redirectUrl | redirect_uri | redirectUri\n// (all redirect field names map to the same value: the URL the IdP\n// should send the browser back to after authentication)\n// - anything else — passed through to the underlying session as-is\n//\n// In all cases the issuer is resolved through\n// /.well-known/openid-configuration before redirect so the canonical\n// issuer host is used.\n\nconst sessionAny = _session as any\nconst originalLogin = typeof sessionAny.login === 'function'\n ? sessionAny.login.bind(_session)\n : undefined\n\nif (originalLogin) {\n const compatLogin = async (idpOrOptions: any, redirectUri?: string): Promise<unknown> => {\n if (idpOrOptions && typeof idpOrOptions === 'object' && !Array.isArray(idpOrOptions)) {\n const oidcIssuer = idpOrOptions.oidcIssuer ?? idpOrOptions.idp ?? idpOrOptions.issuer\n const redirectUrl = idpOrOptions.redirectUrl ?? idpOrOptions.redirect_uri ?? idpOrOptions.redirectUri\n if (typeof oidcIssuer === 'string' && typeof redirectUrl === 'string') {\n return originalLogin(await resolveIssuerForLogin(oidcIssuer), redirectUrl)\n }\n }\n if (typeof idpOrOptions === 'string') {\n return originalLogin(await resolveIssuerForLogin(idpOrOptions), redirectUri)\n }\n return originalLogin(idpOrOptions, redirectUri)\n }\n sessionAny.login = compatLogin as LoginCompat\n}\n\n// ---------------------------------------------------------------------------\n// Legacy event layer\n// ---------------------------------------------------------------------------\n\nconst events = new SessionEvents()\n\n// 'login' and 'sessionRestore' are emitted in SolidAuthnLogic.checkUser()\n// because only that call site knows which path activated the session. Every\n// other identity transition is reported by the identity state, which watches\n// the session itself: 'logout' when the session goes inactive, 'sessionChange'\n// when the identity changes some other way — including a login/logout made in\n// another tab, which uvdsl does not broadcast as a state change and which is\n// noticed when this tab is refocused — and 'identityReplaced' when an\n// established identity is gone.\n//\n// The resync maps a backing store that no longer holds a session (a cross-tab\n// logout) to 'cleared'; the state bounds the wait and drops an answer that\n// belongs to an identity the session has left.\nconst resyncSession = (): unknown => {\n const restoring = restoreSession(_session as unknown as SessionLike)\n if (!restoring) return undefined\n return restoring.then(() => 'changed', (error: unknown) => {\n // A transient refresh/network failure is compared as it stands; a store\n // that has no session to restore means this tab's identity is gone.\n const message = error instanceof Error ? error.message : String(error)\n return /no session to restore/i.test(message) ? 'cleared' : 'changed'\n })\n}\nsubscribeIdentity(_session as unknown as SessionLike, {\n onEvent: (event) => events.emit(event),\n resync: resyncSession\n})\n\nexport const authSession: SessionWithLegacyEvents = Object.assign(\n _session as Omit<OidcSession, 'login'> & { login: LoginCompat },\n { events }\n)\n\n// Legacy `info` compatibility shape.\n// The uvdsl session stores state on `webId_`/`isActive_` and exposes them via\n// `webId`/`isActive` getters, but legacy consumers (e.g. solid-ui's\n// `loginStatusBox` widget, `SolidAuthnLogic.currentUser()`'s fallback path)\n// read `authSession.info.webId` / `authSession.info.isLoggedIn`. Expose those\n// as a derived value — and keep it derived: consumers snapshot and restore\n// `info`, and a retained value would report the previous identity after a\n// login/logout. Assignment is accepted and ignored so ordinary property\n// writes cannot throw; a test that needs to fake `info` redefines it.\nObject.defineProperty(authSession, 'info', {\n enumerable: true,\n configurable: true,\n get (): { webId?: string, isLoggedIn?: boolean } {\n return legacySessionInfo(_session as unknown as SessionLike)\n },\n set (_value: { webId?: string, isLoggedIn?: boolean } | undefined): void {\n // Accepted for legacy code that assigns snapshots; reads stay derived.\n }\n})\n "],"mappings":"kIAoEA,IAAM,EAAa,EAAA,SACb,EAAgB,OAAO,EAAW,OAAU,WAC9C,EAAW,MAAM,KAAK,EAAA,QAAQ,EAC9B,IAAA,GAEA,IAcF,EAAW,MAAQ,MAbQ,EAAmB,IAA2C,CACvF,GAAI,GAAgB,OAAO,GAAiB,UAAY,CAAC,MAAM,QAAQ,CAAY,EAAG,CACpF,IAAM,EAAa,EAAa,YAAc,EAAa,KAAO,EAAa,OACzE,EAAc,EAAa,aAAe,EAAa,cAAgB,EAAa,YAC1F,GAAI,OAAO,GAAe,UAAY,OAAO,GAAgB,SAC3D,OAAO,EAAc,MAAM,EAAA,sBAAsB,CAAU,EAAG,CAAW,CAE7E,CAIA,OAFS,EADL,OAAO,GAAiB,SACL,MAAM,EAAA,sBAAsB,CAAY,EAE1C,EAF6C,CAAW,CAG/E,GAQF,IAAM,EAAS,IAAI,EAAA,cAwBnB,EAAA,kBAAkB,EAAA,SAAoC,CACpD,QAAU,GAAU,EAAO,KAAK,CAAK,EACrC,WAZmC,CACnC,IAAM,EAAY,EAAA,eAAe,EAAA,QAAkC,EAC9D,KACL,OAAO,EAAU,SAAW,UAAY,GAAmB,CAGzD,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,MAAO,yBAAyB,KAAK,CAAO,EAAI,UAAY,SAC9D,CAAC,CACH,CAIA,CAAC,EAED,IAAa,EAAuC,OAAO,OACzD,EAAA,SACA,CAAE,QAAO,CACX,EAWA,OAAO,eAAe,EAAa,OAAQ,CACzC,WAAY,GACZ,aAAc,GACd,KAAiD,CAC/C,OAAO,EAAA,kBAAkB,EAAA,QAAkC,CAC7D,EACA,IAAK,EAAoE,CAEzE,CACF,CAAC"}
1
+ {"version":3,"file":"authSession.cjs.js","names":[],"sources":["../../src/authSession/authSession.ts"],"sourcesContent":["/**\n * Auth session wiring.\n *\n * Takes the raw OIDC session from session.ts and layers on:\n * - Login compatibility shim (normalises legacy call-site signatures\n * and resolves the canonical issuer)\n * - SessionEvents shim (legacy EventEmitter-style API)\n * - Logout listener (emits 'logout' on session deactivation)\n *\n * Exports the fully assembled authSession.\n */\n\nimport type { Session as OidcSession } from '@uvdsl/solid-oidc-client-browser/core'\nimport { _session } from './session'\nimport { resolveIssuerForLogin } from './issuer'\nimport { SessionEvents } from './events'\nimport { legacySessionInfo, restoreSession, subscribeIdentity, type SessionLike } from './identityState'\n\ntype SessionCompatibilityShape = {\n webId?: string\n isActive?: boolean\n info?: {\n webId?: string\n isLoggedIn?: boolean\n }\n fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n authFetch?: (input: string | URL | Request, init?: RequestInit, dpopPayload?: any) => Promise<Response>\n}\n\ntype LoginOptionsLegacy = {\n oidcIssuer?: string\n idp?: string\n issuer?: string\n redirectUrl?: string\n redirect_uri?: string\n redirectUri?: string\n}\n\ntype LoginCompat = {\n (issuer: string, redirectUrl: string): Promise<unknown>\n (options: LoginOptionsLegacy): Promise<unknown>\n}\n\nexport type SessionWithLegacyEvents = Omit<OidcSession, 'login'> & SessionCompatibilityShape & {\n login: LoginCompat\n events: SessionEvents\n}\n\n// ---------------------------------------------------------------------------\n// Login compatibility shim\n// ---------------------------------------------------------------------------\n// Wraps _session.login() so that call sites with different calling\n// conventions all work. The underlying session expects:\n// login(issuer: string, redirectUrl: string)\n//\n// idpOrOptions can be:\n// - a string (issuer URL) — passed through with less resolution\n// - an options object with any of these field-name variants:\n// issuer: oidcIssuer | idp | issuer\n// redirect: redirectUrl | redirect_uri | redirectUri\n// (all redirect field names map to the same value: the URL the IdP\n// should send the browser back to after authentication)\n// - anything else — passed through to the underlying session as-is\n//\n// In all cases the issuer is resolved through\n// /.well-known/openid-configuration before redirect so the canonical\n// issuer host is used.\n\nconst sessionAny = _session as any\nconst originalLogin = typeof sessionAny.login === 'function'\n ? sessionAny.login.bind(_session)\n : undefined\n\nif (originalLogin) {\n const compatLogin = async (idpOrOptions: any, redirectUri?: string): Promise<unknown> => {\n if (idpOrOptions && typeof idpOrOptions === 'object' && !Array.isArray(idpOrOptions)) {\n const oidcIssuer = idpOrOptions.oidcIssuer ?? idpOrOptions.idp ?? idpOrOptions.issuer\n const redirectUrl = idpOrOptions.redirectUrl ?? idpOrOptions.redirect_uri ?? idpOrOptions.redirectUri\n if (typeof oidcIssuer === 'string' && typeof redirectUrl === 'string') {\n return originalLogin(await resolveIssuerForLogin(oidcIssuer), redirectUrl)\n }\n }\n if (typeof idpOrOptions === 'string') {\n return originalLogin(await resolveIssuerForLogin(idpOrOptions), redirectUri)\n }\n return originalLogin(idpOrOptions, redirectUri)\n }\n sessionAny.login = compatLogin as LoginCompat\n}\n\n// ---------------------------------------------------------------------------\n// Legacy event layer\n// ---------------------------------------------------------------------------\n\nconst events = new SessionEvents()\n\n// 'login' and 'sessionRestore' are emitted in SolidAuthnLogic.checkUser()\n// because only that call site knows which path activated the session. Every\n// other identity transition is reported by the identity state, which watches\n// the session itself: 'logout' when the session goes inactive, 'sessionChange'\n// when the identity changes some other way — including a login/logout made in\n// another tab, which uvdsl does not broadcast as a state change and which is\n// noticed when this tab is refocused — and 'identityReplaced' when an\n// established identity is gone.\n//\n// The resync maps a backing store that no longer holds a session (a cross-tab\n// logout) to 'cleared'; the state bounds the wait and drops an answer that\n// belongs to an identity the session has left.\nconst resyncSession = (): unknown => {\n const restoring = restoreSession(_session as unknown as SessionLike)\n if (!restoring) return undefined\n return restoring.then(() => 'changed', (error: unknown) => {\n // A transient refresh/network failure is compared as it stands; a store\n // that has no session to restore means this tab's identity is gone.\n const message = error instanceof Error ? error.message : String(error)\n return /no session to restore/i.test(message) ? 'cleared' : 'changed'\n })\n}\nsubscribeIdentity(_session as unknown as SessionLike, {\n onEvent: (event) => events.emit(event),\n resync: resyncSession\n})\n\nexport const authSession: SessionWithLegacyEvents = Object.assign(\n _session as Omit<OidcSession, 'login'> & { login: LoginCompat },\n { events }\n)\n\n// Legacy `info` compatibility shape.\n// The uvdsl session stores state on `webId_`/`isActive_` and exposes them via\n// `webId`/`isActive` getters, but legacy consumers (e.g. solid-ui's\n// `loginStatusBox` widget, `SolidAuthnLogic.currentUser()`'s fallback path)\n// read `authSession.info.webId` / `authSession.info.isLoggedIn`. Expose those\n// as a derived value — and keep it derived: consumers snapshot and restore\n// `info`, and a retained value would report the previous identity after a\n// login/logout. Assignment is accepted and ignored so ordinary property\n// writes cannot throw; a test that needs to fake `info` redefines it.\nObject.defineProperty(authSession, 'info', {\n enumerable: true,\n configurable: true,\n get (): { webId?: string, isLoggedIn?: boolean } {\n return legacySessionInfo(_session as unknown as SessionLike)\n },\n set (_value: { webId?: string, isLoggedIn?: boolean } | undefined): void {\n // Accepted for legacy code that assigns snapshots; reads stay derived.\n }\n})\n "],"mappings":"kIAoEA,IAAM,EAAa,EAAA,SACb,EAAgB,OAAO,EAAW,OAAU,WAC9C,EAAW,MAAM,KAAK,EAAA,QAAQ,EAC9B,IAAA,GAEA,IAcF,EAAW,MAAQ,MAbQ,EAAmB,IAA2C,CACvF,GAAI,GAAgB,OAAO,GAAiB,UAAY,CAAC,MAAM,QAAQ,CAAY,EAAG,CACpF,IAAM,EAAa,EAAa,YAAc,EAAa,KAAO,EAAa,OACzE,EAAc,EAAa,aAAe,EAAa,cAAgB,EAAa,YAC1F,GAAI,OAAO,GAAe,UAAY,OAAO,GAAgB,SAC3D,OAAO,EAAc,MAAM,EAAA,sBAAsB,CAAU,EAAG,CAAW,CAE7E,CAIA,OAFS,EADL,OAAO,GAAiB,SACL,MAAM,EAAA,sBAAsB,CAAY,EAE1C,EAF6C,CAAW,CAG/E,GAQF,IAAM,EAAS,IAAI,EAAA,cAwBnB,EAAA,kBAAkB,EAAA,SAAoC,CACpD,QAAU,GAAU,EAAO,KAAK,CAAK,EACrC,WAZmC,CACnC,IAAM,EAAY,EAAA,eAAe,EAAA,QAAkC,EACnE,GAAK,EACL,OAAO,EAAU,SAAW,UAAY,GAAmB,CAGzD,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,MAAO,yBAAyB,KAAK,CAAO,EAAI,UAAY,SAC9D,CAAC,CACH,CAIA,CAAC,EAED,IAAa,EAAuC,OAAO,OACzD,EAAA,SACA,CAAE,QAAO,CACX,EAWA,OAAO,eAAe,EAAa,OAAQ,CACzC,WAAY,GACZ,aAAc,GACd,KAAiD,CAC/C,OAAO,EAAA,kBAAkB,EAAA,QAAkC,CAC7D,EACA,IAAK,EAAoE,CAEzE,CACF,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Auth session wiring.
3
+ *
4
+ * Takes the raw OIDC session from session.ts and layers on:
5
+ * - Login compatibility shim (normalises legacy call-site signatures
6
+ * and resolves the canonical issuer)
7
+ * - SessionEvents shim (legacy EventEmitter-style API)
8
+ * - Logout listener (emits 'logout' on session deactivation)
9
+ *
10
+ * Exports the fully assembled authSession.
11
+ */
12
+ import type { Session as OidcSession } from '@uvdsl/solid-oidc-client-browser/core';
13
+ import { SessionEvents } from './events';
14
+ type SessionCompatibilityShape = {
15
+ webId?: string;
16
+ isActive?: boolean;
17
+ info?: {
18
+ webId?: string;
19
+ isLoggedIn?: boolean;
20
+ };
21
+ fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
22
+ authFetch?: (input: string | URL | Request, init?: RequestInit, dpopPayload?: any) => Promise<Response>;
23
+ };
24
+ type LoginOptionsLegacy = {
25
+ oidcIssuer?: string;
26
+ idp?: string;
27
+ issuer?: string;
28
+ redirectUrl?: string;
29
+ redirect_uri?: string;
30
+ redirectUri?: string;
31
+ };
32
+ type LoginCompat = {
33
+ (issuer: string, redirectUrl: string): Promise<unknown>;
34
+ (options: LoginOptionsLegacy): Promise<unknown>;
35
+ };
36
+ export type SessionWithLegacyEvents = Omit<OidcSession, 'login'> & SessionCompatibilityShape & {
37
+ login: LoginCompat;
38
+ events: SessionEvents;
39
+ };
40
+ export declare const authSession: SessionWithLegacyEvents;
41
+ export {};
42
+ //# sourceMappingURL=authSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authSession.d.ts","sourceRoot":"","sources":["../../src/authSession/authSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,uCAAuC,CAAA;AAGnF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGxC,KAAK,yBAAyB,GAAG;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE;QACL,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,UAAU,CAAC,EAAE,OAAO,CAAA;KACrB,CAAA;IACD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC3E,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACxG,CAAA;AAED,KAAK,kBAAkB,GAAG;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IACvD,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,yBAAyB,GAAG;IAC7F,KAAK,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,aAAa,CAAA;CACtB,CAAA;AA6ED,eAAO,MAAM,WAAW,EAAE,uBAGzB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"authSession.esm.js","names":[],"sources":["../../src/authSession/authSession.ts"],"sourcesContent":["/**\n * Auth session wiring.\n *\n * Takes the raw OIDC session from session.ts and layers on:\n * - Login compatibility shim (normalises legacy call-site signatures\n * and resolves the canonical issuer)\n * - SessionEvents shim (legacy EventEmitter-style API)\n * - Logout listener (emits 'logout' on session deactivation)\n *\n * Exports the fully assembled authSession.\n */\n\nimport type { Session as OidcSession } from '@uvdsl/solid-oidc-client-browser/core'\nimport { _session } from './session'\nimport { resolveIssuerForLogin } from './issuer'\nimport { SessionEvents } from './events'\nimport { legacySessionInfo, restoreSession, subscribeIdentity, type SessionLike } from './identityState'\n\ntype SessionCompatibilityShape = {\n webId?: string\n isActive?: boolean\n info?: {\n webId?: string\n isLoggedIn?: boolean\n }\n fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n authFetch?: (input: string | URL | Request, init?: RequestInit, dpopPayload?: any) => Promise<Response>\n}\n\ntype LoginOptionsLegacy = {\n oidcIssuer?: string\n idp?: string\n issuer?: string\n redirectUrl?: string\n redirect_uri?: string\n redirectUri?: string\n}\n\ntype LoginCompat = {\n (issuer: string, redirectUrl: string): Promise<unknown>\n (options: LoginOptionsLegacy): Promise<unknown>\n}\n\nexport type SessionWithLegacyEvents = Omit<OidcSession, 'login'> & SessionCompatibilityShape & {\n login: LoginCompat\n events: SessionEvents\n}\n\n// ---------------------------------------------------------------------------\n// Login compatibility shim\n// ---------------------------------------------------------------------------\n// Wraps _session.login() so that call sites with different calling\n// conventions all work. The underlying session expects:\n// login(issuer: string, redirectUrl: string)\n//\n// idpOrOptions can be:\n// - a string (issuer URL) — passed through with less resolution\n// - an options object with any of these field-name variants:\n// issuer: oidcIssuer | idp | issuer\n// redirect: redirectUrl | redirect_uri | redirectUri\n// (all redirect field names map to the same value: the URL the IdP\n// should send the browser back to after authentication)\n// - anything else — passed through to the underlying session as-is\n//\n// In all cases the issuer is resolved through\n// /.well-known/openid-configuration before redirect so the canonical\n// issuer host is used.\n\nconst sessionAny = _session as any\nconst originalLogin = typeof sessionAny.login === 'function'\n ? sessionAny.login.bind(_session)\n : undefined\n\nif (originalLogin) {\n const compatLogin = async (idpOrOptions: any, redirectUri?: string): Promise<unknown> => {\n if (idpOrOptions && typeof idpOrOptions === 'object' && !Array.isArray(idpOrOptions)) {\n const oidcIssuer = idpOrOptions.oidcIssuer ?? idpOrOptions.idp ?? idpOrOptions.issuer\n const redirectUrl = idpOrOptions.redirectUrl ?? idpOrOptions.redirect_uri ?? idpOrOptions.redirectUri\n if (typeof oidcIssuer === 'string' && typeof redirectUrl === 'string') {\n return originalLogin(await resolveIssuerForLogin(oidcIssuer), redirectUrl)\n }\n }\n if (typeof idpOrOptions === 'string') {\n return originalLogin(await resolveIssuerForLogin(idpOrOptions), redirectUri)\n }\n return originalLogin(idpOrOptions, redirectUri)\n }\n sessionAny.login = compatLogin as LoginCompat\n}\n\n// ---------------------------------------------------------------------------\n// Legacy event layer\n// ---------------------------------------------------------------------------\n\nconst events = new SessionEvents()\n\n// 'login' and 'sessionRestore' are emitted in SolidAuthnLogic.checkUser()\n// because only that call site knows which path activated the session. Every\n// other identity transition is reported by the identity state, which watches\n// the session itself: 'logout' when the session goes inactive, 'sessionChange'\n// when the identity changes some other way — including a login/logout made in\n// another tab, which uvdsl does not broadcast as a state change and which is\n// noticed when this tab is refocused — and 'identityReplaced' when an\n// established identity is gone.\n//\n// The resync maps a backing store that no longer holds a session (a cross-tab\n// logout) to 'cleared'; the state bounds the wait and drops an answer that\n// belongs to an identity the session has left.\nconst resyncSession = (): unknown => {\n const restoring = restoreSession(_session as unknown as SessionLike)\n if (!restoring) return undefined\n return restoring.then(() => 'changed', (error: unknown) => {\n // A transient refresh/network failure is compared as it stands; a store\n // that has no session to restore means this tab's identity is gone.\n const message = error instanceof Error ? error.message : String(error)\n return /no session to restore/i.test(message) ? 'cleared' : 'changed'\n })\n}\nsubscribeIdentity(_session as unknown as SessionLike, {\n onEvent: (event) => events.emit(event),\n resync: resyncSession\n})\n\nexport const authSession: SessionWithLegacyEvents = Object.assign(\n _session as Omit<OidcSession, 'login'> & { login: LoginCompat },\n { events }\n)\n\n// Legacy `info` compatibility shape.\n// The uvdsl session stores state on `webId_`/`isActive_` and exposes them via\n// `webId`/`isActive` getters, but legacy consumers (e.g. solid-ui's\n// `loginStatusBox` widget, `SolidAuthnLogic.currentUser()`'s fallback path)\n// read `authSession.info.webId` / `authSession.info.isLoggedIn`. Expose those\n// as a derived value — and keep it derived: consumers snapshot and restore\n// `info`, and a retained value would report the previous identity after a\n// login/logout. Assignment is accepted and ignored so ordinary property\n// writes cannot throw; a test that needs to fake `info` redefines it.\nObject.defineProperty(authSession, 'info', {\n enumerable: true,\n configurable: true,\n get (): { webId?: string, isLoggedIn?: boolean } {\n return legacySessionInfo(_session as unknown as SessionLike)\n },\n set (_value: { webId?: string, isLoggedIn?: boolean } | undefined): void {\n // Accepted for legacy code that assigns snapshots; reads stay derived.\n }\n})\n "],"mappings":";;;;;AAoEA,IAAM,IAAa,GACb,IAAgB,OAAO,EAAW,SAAU,aAC9C,EAAW,MAAM,KAAK,CAAQ,IAC9B,KAAA;AAEA,MAcF,EAAW,QAAQ,OAbQ,GAAmB,MAA2C;CACvF,IAAI,KAAgB,OAAO,KAAiB,YAAY,CAAC,MAAM,QAAQ,CAAY,GAAG;EACpF,IAAM,IAAa,EAAa,cAAc,EAAa,OAAO,EAAa,QACzE,IAAc,EAAa,eAAe,EAAa,gBAAgB,EAAa;EAC1F,IAAI,OAAO,KAAe,YAAY,OAAO,KAAgB,UAC3D,OAAO,EAAc,MAAM,EAAsB,CAAU,GAAG,CAAW;CAE7E;CAIA,OAFS,EADL,OAAO,KAAiB,WACL,MAAM,EAAsB,CAAY,IAE1C,GAF6C,CAAW;AAG/E;AAQF,IAAM,IAAS,IAAI,EAAc;AAwBjC,EAAkB,GAAoC;CACpD,UAAU,MAAU,EAAO,KAAK,CAAK;CACrC,cAZmC;EACnC,IAAM,IAAY,EAAe,CAAkC;EAC9D,OACL,OAAO,EAAU,WAAW,YAAY,MAAmB;GAGzD,IAAM,IAAU,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK;GACrE,OAAO,yBAAyB,KAAK,CAAO,IAAI,YAAY;EAC9D,CAAC;CACH;AAIA,CAAC;AAED,IAAa,IAAuC,OAAO,OACzD,GACA,EAAE,UAAO,CACX;AAWA,OAAO,eAAe,GAAa,QAAQ;CACzC,YAAY;CACZ,cAAc;CACd,MAAiD;EAC/C,OAAO,EAAkB,CAAkC;CAC7D;CACA,IAAK,GAAoE,CAEzE;AACF,CAAC"}
1
+ {"version":3,"file":"authSession.esm.js","names":[],"sources":["../../src/authSession/authSession.ts"],"sourcesContent":["/**\n * Auth session wiring.\n *\n * Takes the raw OIDC session from session.ts and layers on:\n * - Login compatibility shim (normalises legacy call-site signatures\n * and resolves the canonical issuer)\n * - SessionEvents shim (legacy EventEmitter-style API)\n * - Logout listener (emits 'logout' on session deactivation)\n *\n * Exports the fully assembled authSession.\n */\n\nimport type { Session as OidcSession } from '@uvdsl/solid-oidc-client-browser/core'\nimport { _session } from './session'\nimport { resolveIssuerForLogin } from './issuer'\nimport { SessionEvents } from './events'\nimport { legacySessionInfo, restoreSession, subscribeIdentity, type SessionLike } from './identityState'\n\ntype SessionCompatibilityShape = {\n webId?: string\n isActive?: boolean\n info?: {\n webId?: string\n isLoggedIn?: boolean\n }\n fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>\n authFetch?: (input: string | URL | Request, init?: RequestInit, dpopPayload?: any) => Promise<Response>\n}\n\ntype LoginOptionsLegacy = {\n oidcIssuer?: string\n idp?: string\n issuer?: string\n redirectUrl?: string\n redirect_uri?: string\n redirectUri?: string\n}\n\ntype LoginCompat = {\n (issuer: string, redirectUrl: string): Promise<unknown>\n (options: LoginOptionsLegacy): Promise<unknown>\n}\n\nexport type SessionWithLegacyEvents = Omit<OidcSession, 'login'> & SessionCompatibilityShape & {\n login: LoginCompat\n events: SessionEvents\n}\n\n// ---------------------------------------------------------------------------\n// Login compatibility shim\n// ---------------------------------------------------------------------------\n// Wraps _session.login() so that call sites with different calling\n// conventions all work. The underlying session expects:\n// login(issuer: string, redirectUrl: string)\n//\n// idpOrOptions can be:\n// - a string (issuer URL) — passed through with less resolution\n// - an options object with any of these field-name variants:\n// issuer: oidcIssuer | idp | issuer\n// redirect: redirectUrl | redirect_uri | redirectUri\n// (all redirect field names map to the same value: the URL the IdP\n// should send the browser back to after authentication)\n// - anything else — passed through to the underlying session as-is\n//\n// In all cases the issuer is resolved through\n// /.well-known/openid-configuration before redirect so the canonical\n// issuer host is used.\n\nconst sessionAny = _session as any\nconst originalLogin = typeof sessionAny.login === 'function'\n ? sessionAny.login.bind(_session)\n : undefined\n\nif (originalLogin) {\n const compatLogin = async (idpOrOptions: any, redirectUri?: string): Promise<unknown> => {\n if (idpOrOptions && typeof idpOrOptions === 'object' && !Array.isArray(idpOrOptions)) {\n const oidcIssuer = idpOrOptions.oidcIssuer ?? idpOrOptions.idp ?? idpOrOptions.issuer\n const redirectUrl = idpOrOptions.redirectUrl ?? idpOrOptions.redirect_uri ?? idpOrOptions.redirectUri\n if (typeof oidcIssuer === 'string' && typeof redirectUrl === 'string') {\n return originalLogin(await resolveIssuerForLogin(oidcIssuer), redirectUrl)\n }\n }\n if (typeof idpOrOptions === 'string') {\n return originalLogin(await resolveIssuerForLogin(idpOrOptions), redirectUri)\n }\n return originalLogin(idpOrOptions, redirectUri)\n }\n sessionAny.login = compatLogin as LoginCompat\n}\n\n// ---------------------------------------------------------------------------\n// Legacy event layer\n// ---------------------------------------------------------------------------\n\nconst events = new SessionEvents()\n\n// 'login' and 'sessionRestore' are emitted in SolidAuthnLogic.checkUser()\n// because only that call site knows which path activated the session. Every\n// other identity transition is reported by the identity state, which watches\n// the session itself: 'logout' when the session goes inactive, 'sessionChange'\n// when the identity changes some other way — including a login/logout made in\n// another tab, which uvdsl does not broadcast as a state change and which is\n// noticed when this tab is refocused — and 'identityReplaced' when an\n// established identity is gone.\n//\n// The resync maps a backing store that no longer holds a session (a cross-tab\n// logout) to 'cleared'; the state bounds the wait and drops an answer that\n// belongs to an identity the session has left.\nconst resyncSession = (): unknown => {\n const restoring = restoreSession(_session as unknown as SessionLike)\n if (!restoring) return undefined\n return restoring.then(() => 'changed', (error: unknown) => {\n // A transient refresh/network failure is compared as it stands; a store\n // that has no session to restore means this tab's identity is gone.\n const message = error instanceof Error ? error.message : String(error)\n return /no session to restore/i.test(message) ? 'cleared' : 'changed'\n })\n}\nsubscribeIdentity(_session as unknown as SessionLike, {\n onEvent: (event) => events.emit(event),\n resync: resyncSession\n})\n\nexport const authSession: SessionWithLegacyEvents = Object.assign(\n _session as Omit<OidcSession, 'login'> & { login: LoginCompat },\n { events }\n)\n\n// Legacy `info` compatibility shape.\n// The uvdsl session stores state on `webId_`/`isActive_` and exposes them via\n// `webId`/`isActive` getters, but legacy consumers (e.g. solid-ui's\n// `loginStatusBox` widget, `SolidAuthnLogic.currentUser()`'s fallback path)\n// read `authSession.info.webId` / `authSession.info.isLoggedIn`. Expose those\n// as a derived value — and keep it derived: consumers snapshot and restore\n// `info`, and a retained value would report the previous identity after a\n// login/logout. Assignment is accepted and ignored so ordinary property\n// writes cannot throw; a test that needs to fake `info` redefines it.\nObject.defineProperty(authSession, 'info', {\n enumerable: true,\n configurable: true,\n get (): { webId?: string, isLoggedIn?: boolean } {\n return legacySessionInfo(_session as unknown as SessionLike)\n },\n set (_value: { webId?: string, isLoggedIn?: boolean } | undefined): void {\n // Accepted for legacy code that assigns snapshots; reads stay derived.\n }\n})\n "],"mappings":";;;;;AAoEA,IAAM,IAAa,GACb,IAAgB,OAAO,EAAW,SAAU,aAC9C,EAAW,MAAM,KAAK,CAAQ,IAC9B,KAAA;AAEA,MAcF,EAAW,QAAQ,OAbQ,GAAmB,MAA2C;CACvF,IAAI,KAAgB,OAAO,KAAiB,YAAY,CAAC,MAAM,QAAQ,CAAY,GAAG;EACpF,IAAM,IAAa,EAAa,cAAc,EAAa,OAAO,EAAa,QACzE,IAAc,EAAa,eAAe,EAAa,gBAAgB,EAAa;EAC1F,IAAI,OAAO,KAAe,YAAY,OAAO,KAAgB,UAC3D,OAAO,EAAc,MAAM,EAAsB,CAAU,GAAG,CAAW;CAE7E;CAIA,OAFS,EADL,OAAO,KAAiB,WACL,MAAM,EAAsB,CAAY,IAE1C,GAF6C,CAAW;AAG/E;AAQF,IAAM,IAAS,IAAI,EAAc;AAwBjC,EAAkB,GAAoC;CACpD,UAAU,MAAU,EAAO,KAAK,CAAK;CACrC,cAZmC;EACnC,IAAM,IAAY,EAAe,CAAkC;EACnE,IAAK,GACL,OAAO,EAAU,WAAW,YAAY,MAAmB;GAGzD,IAAM,IAAU,aAAiB,QAAQ,EAAM,UAAU,OAAO,CAAK;GACrE,OAAO,yBAAyB,KAAK,CAAO,IAAI,YAAY;EAC9D,CAAC;CACH;AAIA,CAAC;AAED,IAAa,IAAuC,OAAO,OACzD,GACA,EAAE,UAAO,CACX;AAWA,OAAO,eAAe,GAAa,QAAQ;CACzC,YAAY;CACZ,cAAc;CACd,MAAiD;EAC/C,OAAO,EAAkB,CAAkC;CAC7D;CACA,IAAK,GAAoE,CAEzE;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.cjs.js","names":[],"sources":["../../src/authSession/events.ts"],"sourcesContent":["/**\n * Legacy event compatibility layer.\n *\n * Pure EventEmitter-style shim — no side effects, no uvdsl dependencies.\n * Wired into the auth session by authSession.ts.\n */\n\nexport type LegacyEventName = 'identityReplaced' | 'login' | 'logout' | 'sessionChange' | 'sessionRestore'\ntype LegacyEventHandler = (...args: unknown[]) => void\n\n/**\n * Minimal EventEmitter-style shim so that existing consumers using\n * `authSession.events.on('login' | 'logout' | 'sessionRestore', handler)`\n * continue working without modification.\n *\n * Events are emitted by SolidAuthnLogic.checkUser() (login/sessionRestore)\n * and by the identity state in identityState.ts ('logout', 'sessionChange',\n * 'identityReplaced' — the event the reload helper subscribes to).\n */\nexport class SessionEvents {\n private readonly listeners: Map<string, Set<LegacyEventHandler>> = new Map()\n\n on (event: LegacyEventName, handler: LegacyEventHandler): void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n this.listeners.get(event)!.add(handler)\n }\n\n off (event: LegacyEventName, handler: LegacyEventHandler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n emit (event: LegacyEventName, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach(h => h(...args))\n }\n}\n"],"mappings":"AAmBA,IAAa,EAAb,KAA2B,8BAC0C,IAAI,IAEvE,GAAI,EAAwB,EAAmC,CACxD,KAAK,UAAU,IAAI,CAAK,GAAG,KAAK,UAAU,IAAI,EAAO,IAAI,GAAK,EACnE,KAAK,UAAU,IAAI,CAAK,CAAC,CAAE,IAAI,CAAO,CACxC,CAEA,IAAK,EAAwB,EAAmC,CAC9D,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,OAAO,CAAO,CAC3C,CAEA,KAAM,EAAwB,GAAG,EAAuB,CACtD,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,QAAQ,GAAK,EAAE,GAAG,CAAI,CAAC,CACpD,CACF"}
1
+ {"version":3,"file":"events.cjs.js","names":[],"sources":["../../src/authSession/events.ts"],"sourcesContent":["/**\n * Legacy event compatibility layer.\n *\n * Pure EventEmitter-style shim — no side effects, no uvdsl dependencies.\n * Wired into the auth session by authSession.ts.\n */\n\nexport type LegacyEventName = 'identityReplaced' | 'login' | 'logout' | 'sessionChange' | 'sessionRestore'\ntype LegacyEventHandler = (...args: unknown[]) => void\n\n/**\n * Minimal EventEmitter-style shim so that existing consumers using\n * `authSession.events.on('login' | 'logout' | 'sessionRestore', handler)`\n * continue working without modification.\n *\n * Events are emitted by SolidAuthnLogic.checkUser() (login/sessionRestore)\n * and by the identity state in identityState.ts ('logout', 'sessionChange',\n * 'identityReplaced' — the event the reload helper subscribes to).\n */\nexport class SessionEvents {\n private readonly listeners: Map<string, Set<LegacyEventHandler>> = new Map()\n\n on (event: LegacyEventName, handler: LegacyEventHandler): void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n this.listeners.get(event)!.add(handler)\n }\n\n off (event: LegacyEventName, handler: LegacyEventHandler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n emit (event: LegacyEventName, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach(h => h(...args))\n }\n}\n"],"mappings":"AAmBA,IAAa,EAAb,KAA2B,eAC0C,KAAA,UAAA,IAAI,IAEvE,GAAI,EAAwB,EAAmC,CACxD,KAAK,UAAU,IAAI,CAAK,GAAG,KAAK,UAAU,IAAI,EAAO,IAAI,GAAK,EACnE,KAAK,UAAU,IAAI,CAAK,CAAC,CAAE,IAAI,CAAO,CACxC,CAEA,IAAK,EAAwB,EAAmC,CAC9D,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,OAAO,CAAO,CAC3C,CAEA,KAAM,EAAwB,GAAG,EAAuB,CACtD,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,QAAQ,GAAK,EAAE,GAAG,CAAI,CAAC,CACpD,CACF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Legacy event compatibility layer.
3
+ *
4
+ * Pure EventEmitter-style shim — no side effects, no uvdsl dependencies.
5
+ * Wired into the auth session by authSession.ts.
6
+ */
7
+ export type LegacyEventName = 'identityReplaced' | 'login' | 'logout' | 'sessionChange' | 'sessionRestore';
8
+ type LegacyEventHandler = (...args: unknown[]) => void;
9
+ /**
10
+ * Minimal EventEmitter-style shim so that existing consumers using
11
+ * `authSession.events.on('login' | 'logout' | 'sessionRestore', handler)`
12
+ * continue working without modification.
13
+ *
14
+ * Events are emitted by SolidAuthnLogic.checkUser() (login/sessionRestore)
15
+ * and by the identity state in identityState.ts ('logout', 'sessionChange',
16
+ * 'identityReplaced' — the event the reload helper subscribes to).
17
+ */
18
+ export declare class SessionEvents {
19
+ private readonly listeners;
20
+ on(event: LegacyEventName, handler: LegacyEventHandler): void;
21
+ off(event: LegacyEventName, handler: LegacyEventHandler): void;
22
+ emit(event: LegacyEventName, ...args: unknown[]): void;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/authSession/events.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,OAAO,GAAG,QAAQ,GAAG,eAAe,GAAG,gBAAgB,CAAA;AAC1G,KAAK,kBAAkB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;AAEtD;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkD;IAE5E,EAAE,CAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAK9D,GAAG,CAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,kBAAkB,GAAG,IAAI;IAI/D,IAAI,CAAE,KAAK,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGxD"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.esm.js","names":[],"sources":["../../src/authSession/events.ts"],"sourcesContent":["/**\n * Legacy event compatibility layer.\n *\n * Pure EventEmitter-style shim — no side effects, no uvdsl dependencies.\n * Wired into the auth session by authSession.ts.\n */\n\nexport type LegacyEventName = 'identityReplaced' | 'login' | 'logout' | 'sessionChange' | 'sessionRestore'\ntype LegacyEventHandler = (...args: unknown[]) => void\n\n/**\n * Minimal EventEmitter-style shim so that existing consumers using\n * `authSession.events.on('login' | 'logout' | 'sessionRestore', handler)`\n * continue working without modification.\n *\n * Events are emitted by SolidAuthnLogic.checkUser() (login/sessionRestore)\n * and by the identity state in identityState.ts ('logout', 'sessionChange',\n * 'identityReplaced' — the event the reload helper subscribes to).\n */\nexport class SessionEvents {\n private readonly listeners: Map<string, Set<LegacyEventHandler>> = new Map()\n\n on (event: LegacyEventName, handler: LegacyEventHandler): void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n this.listeners.get(event)!.add(handler)\n }\n\n off (event: LegacyEventName, handler: LegacyEventHandler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n emit (event: LegacyEventName, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach(h => h(...args))\n }\n}\n"],"mappings":";AAmBA,IAAa,IAAb,MAA2B;;mCAC0C,IAAI,IAAI;;CAE3E,GAAI,GAAwB,GAAmC;EAE7D,AADK,KAAK,UAAU,IAAI,CAAK,KAAG,KAAK,UAAU,IAAI,mBAAO,IAAI,IAAI,CAAC,GACnE,KAAK,UAAU,IAAI,CAAK,CAAC,CAAE,IAAI,CAAO;CACxC;CAEA,IAAK,GAAwB,GAAmC;EAC9D,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,OAAO,CAAO;CAC3C;CAEA,KAAM,GAAwB,GAAG,GAAuB;EACtD,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,SAAQ,MAAK,EAAE,GAAG,CAAI,CAAC;CACpD;AACF"}
1
+ {"version":3,"file":"events.esm.js","names":[],"sources":["../../src/authSession/events.ts"],"sourcesContent":["/**\n * Legacy event compatibility layer.\n *\n * Pure EventEmitter-style shim — no side effects, no uvdsl dependencies.\n * Wired into the auth session by authSession.ts.\n */\n\nexport type LegacyEventName = 'identityReplaced' | 'login' | 'logout' | 'sessionChange' | 'sessionRestore'\ntype LegacyEventHandler = (...args: unknown[]) => void\n\n/**\n * Minimal EventEmitter-style shim so that existing consumers using\n * `authSession.events.on('login' | 'logout' | 'sessionRestore', handler)`\n * continue working without modification.\n *\n * Events are emitted by SolidAuthnLogic.checkUser() (login/sessionRestore)\n * and by the identity state in identityState.ts ('logout', 'sessionChange',\n * 'identityReplaced' — the event the reload helper subscribes to).\n */\nexport class SessionEvents {\n private readonly listeners: Map<string, Set<LegacyEventHandler>> = new Map()\n\n on (event: LegacyEventName, handler: LegacyEventHandler): void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set())\n this.listeners.get(event)!.add(handler)\n }\n\n off (event: LegacyEventName, handler: LegacyEventHandler): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n emit (event: LegacyEventName, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach(h => h(...args))\n }\n}\n"],"mappings":";AAmBA,IAAa,IAAb,MAA2B;;EAC0C,KAAA,4BAAA,IAAI,IAAI;;CAE3E,GAAI,GAAwB,GAAmC;EAE7D,AADK,KAAK,UAAU,IAAI,CAAK,KAAG,KAAK,UAAU,IAAI,mBAAO,IAAI,IAAI,CAAC,GACnE,KAAK,UAAU,IAAI,CAAK,CAAC,CAAE,IAAI,CAAO;CACxC;CAEA,IAAK,GAAwB,GAAmC;EAC9D,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,OAAO,CAAO;CAC3C;CAEA,KAAM,GAAwB,GAAG,GAAuB;EACtD,KAAK,UAAU,IAAI,CAAK,CAAC,EAAE,SAAQ,MAAK,EAAE,GAAG,CAAI,CAAC;CACpD;AACF"}