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.
- package/dist/_virtual/_rolldown/runtime.cjs.js +1 -1
- package/dist/acl/accessControlSubjects.cjs.js +2 -0
- package/dist/acl/accessControlSubjects.cjs.js.map +1 -0
- package/dist/acl/accessControlSubjects.d.ts +8 -0
- package/dist/acl/accessControlSubjects.d.ts.map +1 -0
- package/dist/acl/accessControlSubjects.esm.js +75 -0
- package/dist/acl/accessControlSubjects.esm.js.map +1 -0
- package/dist/acl/aclLogic.cjs.js +1 -1
- package/dist/acl/aclLogic.cjs.js.map +1 -1
- package/dist/acl/aclLogic.d.ts +7 -0
- package/dist/acl/aclLogic.d.ts.map +1 -0
- package/dist/acl/aclLogic.esm.js +111 -27
- package/dist/acl/aclLogic.esm.js.map +1 -1
- package/dist/authSession/authSession.cjs.js.map +1 -1
- package/dist/authSession/authSession.d.ts +42 -0
- package/dist/authSession/authSession.d.ts.map +1 -0
- package/dist/authSession/authSession.esm.js.map +1 -1
- package/dist/authSession/events.cjs.js.map +1 -1
- package/dist/authSession/events.d.ts +25 -0
- package/dist/authSession/events.d.ts.map +1 -0
- package/dist/authSession/events.esm.js.map +1 -1
- package/dist/authSession/flagAuthorizationOnTransitions.cjs.js +1 -1
- package/dist/authSession/flagAuthorizationOnTransitions.cjs.js.map +1 -1
- package/dist/authSession/flagAuthorizationOnTransitions.d.ts +76 -0
- package/dist/authSession/flagAuthorizationOnTransitions.d.ts.map +1 -0
- package/dist/authSession/flagAuthorizationOnTransitions.esm.js +1 -1
- package/dist/authSession/flagAuthorizationOnTransitions.esm.js.map +1 -1
- package/dist/authSession/identityState.cjs.js +1 -1
- package/dist/authSession/identityState.cjs.js.map +1 -1
- package/dist/authSession/identityState.d.ts +199 -0
- package/dist/authSession/identityState.d.ts.map +1 -0
- package/dist/authSession/identityState.esm.js +1 -1
- package/dist/authSession/identityState.esm.js.map +1 -1
- package/dist/authSession/issuer.d.ts +8 -0
- package/dist/authSession/issuer.d.ts.map +1 -0
- package/dist/authSession/session.cjs.js +1 -1
- package/dist/authSession/session.cjs.js.map +1 -1
- package/dist/authSession/session.d.ts +45 -0
- package/dist/authSession/session.d.ts.map +1 -0
- package/dist/authSession/session.esm.js +1 -1
- package/dist/authSession/session.esm.js.map +1 -1
- package/dist/authn/SolidAuthnLogic.cjs.js.map +1 -1
- package/dist/authn/SolidAuthnLogic.d.ts +61 -0
- package/dist/authn/SolidAuthnLogic.d.ts.map +1 -0
- package/dist/authn/SolidAuthnLogic.esm.js.map +1 -1
- package/dist/authn/authUtil.cjs.js.map +1 -1
- package/dist/authn/authUtil.d.ts +17 -0
- package/dist/authn/authUtil.d.ts.map +1 -0
- package/dist/authn/serverLogout.d.ts +6 -0
- package/dist/authn/serverLogout.d.ts.map +1 -0
- package/dist/chat/chatLogic.cjs.js +1 -1
- package/dist/chat/chatLogic.cjs.js.map +1 -1
- package/dist/chat/chatLogic.d.ts +3 -0
- package/dist/chat/chatLogic.d.ts.map +1 -0
- package/dist/chat/chatLogic.esm.js +5 -5
- package/dist/chat/chatLogic.esm.js.map +1 -1
- package/dist/directory/catalogDirectory.cjs.js +2 -0
- package/dist/directory/catalogDirectory.cjs.js.map +1 -0
- package/dist/directory/catalogDirectory.d.ts +5 -0
- package/dist/directory/catalogDirectory.d.ts.map +1 -0
- package/dist/directory/catalogDirectory.esm.js +54 -0
- package/dist/directory/catalogDirectory.esm.js.map +1 -0
- package/dist/directory/contactsDirectory.cjs.js +2 -0
- package/dist/directory/contactsDirectory.cjs.js.map +1 -0
- package/dist/directory/contactsDirectory.d.ts +7 -0
- package/dist/directory/contactsDirectory.d.ts.map +1 -0
- package/dist/directory/contactsDirectory.esm.js +91 -0
- package/dist/directory/contactsDirectory.esm.js.map +1 -0
- package/dist/directory/directoryHelpers.cjs.js +2 -0
- package/dist/directory/directoryHelpers.cjs.js.map +1 -0
- package/dist/directory/directoryHelpers.d.ts +18 -0
- package/dist/directory/directoryHelpers.d.ts.map +1 -0
- package/dist/directory/directoryHelpers.esm.js +89 -0
- package/dist/directory/directoryHelpers.esm.js.map +1 -0
- package/dist/directory/directoryLogic.cjs.js +2 -0
- package/dist/directory/directoryLogic.cjs.js.map +1 -0
- package/dist/directory/directoryLogic.d.ts +6 -0
- package/dist/directory/directoryLogic.d.ts.map +1 -0
- package/dist/directory/directoryLogic.esm.js +41 -0
- package/dist/directory/directoryLogic.esm.js.map +1 -0
- package/dist/directory/friendsDirectory.cjs.js +2 -0
- package/dist/directory/friendsDirectory.cjs.js.map +1 -0
- package/dist/directory/friendsDirectory.d.ts +6 -0
- package/dist/directory/friendsDirectory.d.ts.map +1 -0
- package/dist/directory/friendsDirectory.esm.js +58 -0
- package/dist/directory/friendsDirectory.esm.js.map +1 -0
- package/dist/inbox/inboxLogic.d.ts +3 -0
- package/dist/inbox/inboxLogic.d.ts.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.esm.js +10 -9
- package/dist/index.esm.js.map +1 -1
- package/dist/issuer/issuerLogic.d.ts +8 -0
- package/dist/issuer/issuerLogic.d.ts.map +1 -0
- package/dist/logic/CustomError.cjs.js.map +1 -1
- package/dist/logic/CustomError.d.ts +21 -0
- package/dist/logic/CustomError.d.ts.map +1 -0
- package/dist/logic/CustomError.esm.js.map +1 -1
- package/dist/logic/solidLogic.cjs.js +1 -1
- package/dist/logic/solidLogic.cjs.js.map +1 -1
- package/dist/logic/solidLogic.d.ts +6 -0
- package/dist/logic/solidLogic.d.ts.map +1 -0
- package/dist/logic/solidLogic.esm.js +29 -27
- package/dist/logic/solidLogic.esm.js.map +1 -1
- package/dist/logic/solidLogicSingleton.cjs.js +1 -1
- package/dist/logic/solidLogicSingleton.cjs.js.map +1 -1
- package/dist/logic/solidLogicSingleton.d.ts +4 -0
- package/dist/logic/solidLogicSingleton.d.ts.map +1 -0
- package/dist/logic/solidLogicSingleton.esm.js +2 -1
- package/dist/logic/solidLogicSingleton.esm.js.map +1 -1
- package/dist/profile/profileAclDocuments.d.ts +2 -0
- package/dist/profile/profileAclDocuments.d.ts.map +1 -0
- package/dist/profile/profileDocuments.d.ts +2 -0
- package/dist/profile/profileDocuments.d.ts.map +1 -0
- package/dist/profile/profileLogic.cjs.js.map +1 -1
- package/dist/profile/profileLogic.d.ts +3 -0
- package/dist/profile/profileLogic.d.ts.map +1 -0
- package/dist/profile/profileLogic.esm.js +2 -1
- package/dist/profile/profileLogic.esm.js.map +1 -1
- package/dist/resource/resourceHttp.d.ts +5 -0
- package/dist/resource/resourceHttp.d.ts.map +1 -0
- package/dist/resource/resourceLogic.cjs.js +1 -1
- package/dist/resource/resourceLogic.cjs.js.map +1 -1
- package/dist/resource/resourceLogic.d.ts +4 -0
- package/dist/resource/resourceLogic.d.ts.map +1 -0
- package/dist/resource/resourceLogic.esm.js +36 -26
- package/dist/resource/resourceLogic.esm.js.map +1 -1
- package/dist/resource/resourceMetadata.d.ts +5 -0
- package/dist/resource/resourceMetadata.d.ts.map +1 -0
- package/dist/typeIndex/typeIndexAclDocuments.d.ts +2 -0
- package/dist/typeIndex/typeIndexAclDocuments.d.ts.map +1 -0
- package/dist/typeIndex/typeIndexDocuments.d.ts +3 -0
- package/dist/typeIndex/typeIndexDocuments.d.ts.map +1 -0
- package/dist/typeIndex/typeIndexLogic.cjs.js.map +1 -1
- package/dist/typeIndex/typeIndexLogic.d.ts +3 -0
- package/dist/typeIndex/typeIndexLogic.d.ts.map +1 -0
- package/dist/typeIndex/typeIndexLogic.esm.js +10 -5
- package/dist/typeIndex/typeIndexLogic.esm.js.map +1 -1
- package/dist/types.d.ts +187 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/util/containerLogic.cjs.js.map +1 -1
- package/dist/util/containerLogic.d.ts +12 -0
- package/dist/util/containerLogic.d.ts.map +1 -0
- package/dist/util/containerLogic.esm.js.map +1 -1
- package/dist/util/debug.d.ts +5 -0
- package/dist/util/debug.d.ts.map +1 -0
- package/dist/util/ns.cjs.js.map +1 -1
- package/dist/util/ns.d.ts +2 -0
- package/dist/util/ns.d.ts.map +1 -0
- package/dist/util/utilityLogic.cjs.js +1 -1
- package/dist/util/utilityLogic.cjs.js.map +1 -1
- package/dist/util/utilityLogic.d.ts +16 -0
- package/dist/util/utilityLogic.d.ts.map +1 -0
- package/dist/util/utilityLogic.esm.js +6 -2
- package/dist/util/utilityLogic.esm.js.map +1 -1
- package/dist/util/utils.cjs.js +1 -1
- package/dist/util/utils.cjs.js.map +1 -1
- package/dist/util/utils.d.ts +8 -0
- package/dist/util/utils.d.ts.map +1 -0
- package/dist/util/utils.esm.js +5 -3
- package/dist/util/utils.esm.js.map +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authUtil.cjs.js","names":[],"sources":["../../src/authn/authUtil.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport * as debug from '../util/debug'\n\n/**\n * find a user or app's context as set in window.SolidAppContext\n * this is a const, not a function, because we have problems to jest mock it otherwise\n * see: https://github.com/facebook/jest/issues/936#issuecomment-545080082 for more\n * @return {any} - an appContext object\n */\nexport const appContext = ():any => {\n let { SolidAppContext }: any = window\n SolidAppContext ||= {}\n SolidAppContext.viewingNoAuthPage = false\n if (SolidAppContext.noAuth && window.document) {\n const currentPage = window.document.location.href\n if (currentPage.startsWith(SolidAppContext.noAuth)) {\n SolidAppContext.viewingNoAuthPage = true\n const params = new URLSearchParams(window.document.location.search)\n if (params) {\n let viewedPage = SolidAppContext.viewedPage = params.get('uri') || null\n if (viewedPage) {\n viewedPage = decodeURI(viewedPage)\n if (!viewedPage.startsWith(SolidAppContext.noAuth)) {\n const ary = viewedPage.split(/\\//)\n SolidAppContext.idp = ary[0] + '//' + ary[2]\n SolidAppContext.viewingNoAuthPage = false\n }\n }\n }\n }\n }\n return SolidAppContext\n}\n\n/**\n * Returns `sym($SolidTestEnvironment.username)` if\n * `$SolidTestEnvironment.username` is defined as a global\n * or \n * returns testID defined in the HTML page\n * @returns {NamedNode|null}\n */\nexport function offlineTestID (): NamedNode | null {\n const { $SolidTestEnvironment }: any = window\n if (\n typeof $SolidTestEnvironment !== 'undefined' &&\n $SolidTestEnvironment.username\n ) {\n // Test setup\n debug.log('Assuming the user is ' + $SolidTestEnvironment.username)\n return sym($SolidTestEnvironment.username)\n }\n // hack that makes SolidOS work in offline mode by adding the webId directly in html\n // example usage: https://github.com/solidos/mashlib/blob/29b8b53c46bf02e0e219f0bacd51b0e9951001dd/test/contact/local.html#L37\n if (\n typeof document !== 'undefined' &&\n document.location &&\n ('' + document.location).slice(0, 16) === 'http://localhost'\n ) {\n const div = document.getElementById('appTarget')\n if (!div) return null\n const id = div.getAttribute('testID')\n if (!id) return null\n debug.log('Assuming user is ' + id)\n return sym(id)\n }\n return null\n}\n"],"mappings":"gEASA,IAAa,MAAuB,CAChC,GAAI,CAAE,mBAAyB,OAG/B,GAFA,IAAoB,CAAC,EACrB,EAAgB,kBAAoB,GAChC,EAAgB,QAAU,OAAO,UACb,OAAO,SAAS,SAAS,KAC7B,WAAW,EAAgB,MAAM,EAAG,CACpD,EAAgB,kBAAoB,GACpC,IAAM,EAAS,IAAI,gBAAgB,OAAO,SAAS,SAAS,MAAM,EAClE,GAAI,EAAQ,CACR,IAAI,EAAa,EAAgB,WAAa,EAAO,IAAI,KAAK,GAAK,KACnE,GAAI,IACJ,EAAa,UAAU,CAAU,EAC7B,CAAC,EAAW,WAAW,EAAgB,MAAM,GAAG,CAChD,IAAM,EAAM,EAAW,MAAM,IAAI,EACjC,EAAgB,IAAM,EAAI,GAAK,KAAO,EAAI,GAC1C,EAAgB,kBAAoB,EACxC,CAEJ,CACA,CAEJ,OAAO,CACX,EASA,SAAgB,GAAmC,CAC/C,GAAM,CAAE,yBAA+B,OACvC,GACS,IAA0B,QACjC,EAAsB,SAItB,OADA,EAAA,IAAU,wBAA0B,EAAsB,QAAQ,GAClE,
|
|
1
|
+
{"version":3,"file":"authUtil.cjs.js","names":[],"sources":["../../src/authn/authUtil.ts"],"sourcesContent":["import { NamedNode, sym } from 'rdflib'\nimport * as debug from '../util/debug'\n\n/**\n * find a user or app's context as set in window.SolidAppContext\n * this is a const, not a function, because we have problems to jest mock it otherwise\n * see: https://github.com/facebook/jest/issues/936#issuecomment-545080082 for more\n * @return {any} - an appContext object\n */\nexport const appContext = ():any => {\n let { SolidAppContext }: any = window\n SolidAppContext ||= {}\n SolidAppContext.viewingNoAuthPage = false\n if (SolidAppContext.noAuth && window.document) {\n const currentPage = window.document.location.href\n if (currentPage.startsWith(SolidAppContext.noAuth)) {\n SolidAppContext.viewingNoAuthPage = true\n const params = new URLSearchParams(window.document.location.search)\n if (params) {\n let viewedPage = SolidAppContext.viewedPage = params.get('uri') || null\n if (viewedPage) {\n viewedPage = decodeURI(viewedPage)\n if (!viewedPage.startsWith(SolidAppContext.noAuth)) {\n const ary = viewedPage.split(/\\//)\n SolidAppContext.idp = ary[0] + '//' + ary[2]\n SolidAppContext.viewingNoAuthPage = false\n }\n }\n }\n }\n }\n return SolidAppContext\n}\n\n/**\n * Returns `sym($SolidTestEnvironment.username)` if\n * `$SolidTestEnvironment.username` is defined as a global\n * or \n * returns testID defined in the HTML page\n * @returns {NamedNode|null}\n */\nexport function offlineTestID (): NamedNode | null {\n const { $SolidTestEnvironment }: any = window\n if (\n typeof $SolidTestEnvironment !== 'undefined' &&\n $SolidTestEnvironment.username\n ) {\n // Test setup\n debug.log('Assuming the user is ' + $SolidTestEnvironment.username)\n return sym($SolidTestEnvironment.username)\n }\n // hack that makes SolidOS work in offline mode by adding the webId directly in html\n // example usage: https://github.com/solidos/mashlib/blob/29b8b53c46bf02e0e219f0bacd51b0e9951001dd/test/contact/local.html#L37\n if (\n typeof document !== 'undefined' &&\n document.location &&\n ('' + document.location).slice(0, 16) === 'http://localhost'\n ) {\n const div = document.getElementById('appTarget')\n if (!div) return null\n const id = div.getAttribute('testID')\n if (!id) return null\n debug.log('Assuming user is ' + id)\n return sym(id)\n }\n return null\n}\n"],"mappings":"gEASA,IAAa,MAAuB,CAChC,GAAI,CAAE,mBAAyB,OAG/B,GAFA,IAAoB,CAAC,EACrB,EAAgB,kBAAoB,GAChC,EAAgB,QAAU,OAAO,UACb,OAAO,SAAS,SAAS,KAC7B,WAAW,EAAgB,MAAM,EAAG,CACpD,EAAgB,kBAAoB,GACpC,IAAM,EAAS,IAAI,gBAAgB,OAAO,SAAS,SAAS,MAAM,EAClE,GAAI,EAAQ,CACR,IAAI,EAAa,EAAgB,WAAa,EAAO,IAAI,KAAK,GAAK,KACnE,GAAI,IACJ,EAAa,UAAU,CAAU,EAC7B,CAAC,EAAW,WAAW,EAAgB,MAAM,GAAG,CAChD,IAAM,EAAM,EAAW,MAAM,IAAI,EACjC,EAAgB,IAAM,EAAI,GAAK,KAAO,EAAI,GAC1C,EAAgB,kBAAoB,EACxC,CAEJ,CACA,CAEJ,OAAO,CACX,EASA,SAAgB,GAAmC,CAC/C,GAAM,CAAE,yBAA+B,OACvC,GACS,IAA0B,QACjC,EAAsB,SAItB,OADA,EAAA,IAAU,wBAA0B,EAAsB,QAAQ,GAClE,EAAO,EAAA,IAAA,CAAI,EAAsB,QAAQ,EAI3C,GACE,OAAO,SAAa,KACpB,SAAS,WACR,GAAK,SAAS,SAAA,CAAU,MAAM,EAAG,EAAE,IAAM,mBAC1C,CACA,IAAM,EAAM,SAAS,eAAe,WAAW,EAC/C,GAAI,CAAC,EAAK,OAAO,KACjB,IAAM,EAAK,EAAI,aAAa,QAAQ,EAGpC,OAFK,GACL,EAAA,IAAU,oBAAsB,CAAE,GAClC,EAAO,EAAA,IAAA,CAAI,CAAE,GAFG,IAGlB,CACA,OAAO,IACX"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NamedNode } from 'rdflib';
|
|
2
|
+
/**
|
|
3
|
+
* find a user or app's context as set in window.SolidAppContext
|
|
4
|
+
* this is a const, not a function, because we have problems to jest mock it otherwise
|
|
5
|
+
* see: https://github.com/facebook/jest/issues/936#issuecomment-545080082 for more
|
|
6
|
+
* @return {any} - an appContext object
|
|
7
|
+
*/
|
|
8
|
+
export declare const appContext: () => any;
|
|
9
|
+
/**
|
|
10
|
+
* Returns `sym($SolidTestEnvironment.username)` if
|
|
11
|
+
* `$SolidTestEnvironment.username` is defined as a global
|
|
12
|
+
* or
|
|
13
|
+
* returns testID defined in the HTML page
|
|
14
|
+
* @returns {NamedNode|null}
|
|
15
|
+
*/
|
|
16
|
+
export declare function offlineTestID(): NamedNode | null;
|
|
17
|
+
//# sourceMappingURL=authUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authUtil.d.ts","sourceRoot":"","sources":["../../src/authn/authUtil.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAO,MAAM,QAAQ,CAAA;AAGvC;;;;;GAKG;AACH,eAAO,MAAM,UAAU,QAAM,GAuB5B,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,IAAK,SAAS,GAAG,IAAI,CAyBjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverLogout.d.ts","sourceRoot":"","sources":["../../src/authn/serverLogout.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC,CAAA;AAED,wBAAsB,uBAAuB,CAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAqClG"}
|
|
@@ -14,7 +14,7 @@ const e=require("../util/ns.cjs.js"),t=require("../util/utils.cjs.js");let n=req
|
|
|
14
14
|
acl:default <.>;
|
|
15
15
|
acl:mode
|
|
16
16
|
acl:Read, acl:Append.
|
|
17
|
-
`;await i.fetcher.webOperation(`PUT`,a.value,{data:o,contentType:`text/turtle`})}async function c(e,r){let a=i.any(r,o.solid(`privateTypeIndex`));if(!a)throw Error(`Private type index not found!`);await i.fetcher.load(a);let s=t.newThing(a),c=[(0,n.st)(s,o.rdf(`type`),o.solid(`TypeRegistration`),a.doc()),(0,n.st)(s,o.solid(`forClass`),o.meeting(`LongChat`),a.doc()),(0,n.st)(s,o.solid(`instance`),e,a.doc())];await new Promise((e,t)=>{i.updater.update([],c,function(n,r,i){r?e(null):t(Error(i))})})}async function l(e){let r=await a.loadMe(),o=
|
|
17
|
+
`;await i.fetcher.webOperation(`PUT`,a.value,{data:o,contentType:`text/turtle`})}async function c(e,r){let a=i.any(r,o.solid(`privateTypeIndex`));if(!a)throw Error(`Private type index not found!`);await i.fetcher.load(a);let s=t.newThing(a),c=[(0,n.st)(s,o.rdf(`type`),o.solid(`TypeRegistration`),a.doc()),(0,n.st)(s,o.solid(`forClass`),o.meeting(`LongChat`),a.doc()),(0,n.st)(s,o.solid(`instance`),e,a.doc())];await new Promise((e,t)=>{i.updater.update([],c,function(n,r,i){r?e(null):t(Error(i))})})}async function l(e){let r=await a.loadMe(),o=await a.getPodRoot(r),s=t.determineChatContainer(e,o),c=!0;try{await i.fetcher.load(new n.NamedNode(s.value+`index.ttl#this`))}catch{c=!1}return{me:r,chatContainer:s,exists:c}}async function u(e,t){return(await d({me:t,newBase:e.value})).newInstance}function d(e){let t=i,a=t.updater;if(e.me&&!e.me.uri)throw Error(`chat mintNew: Invalid userid `+e.me);let s=e.newInstance=e.newInstance||t.sym(e.newBase+r),c=s.doc();return t.add(s,o.rdf(`type`),o.meeting(`LongChat`),c),t.add(s,o.dc(`title`),`Chat channel`,c),t.add(s,o.dc(`created`),(0,n.term)(new Date(Date.now())),c),e.me&&t.add(s,o.dc(`author`),e.me,c),new Promise(function(n,r){a?.put(c,t.statementsMatching(void 0,void 0,void 0,c),`text/turtle`,function(t,i,a){i?n({...e,newInstance:s}):r(Error(`FAILED to save new chat channel at: `+t+` : `+a))})})}async function f(e,t=!0){let{me:i,chatContainer:a,exists:o}=await l(e);if(o)return new n.NamedNode(a.value+r);if(t){let t=await u(a,i);return await p(e,t),await s(a,i,e),await c(t,i),t}return null}async function p(e,t){await i.fetcher.load(e.doc());let n=i.any(e,o.ldp(`inbox`),void 0,e.doc());if(!n)throw Error(`Invitee inbox not found! ${e.value}`);let r=`
|
|
18
18
|
<> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;
|
|
19
19
|
${o.rdf(`seeAlso`)} <${t.value}> .
|
|
20
20
|
`,a=await i.fetcher?.webOperation(`POST`,n.value,{data:r,contentType:`text/turtle`});if(!a?.headers.get(`location`))throw Error(`Invite sending returned a ${a?.status}`)}return{setAcl:s,addToPrivateTypeIndex:c,findChat:l,createChatThing:u,getChat:f,sendInvite:p,mintNew:d}}exports.createChatLogic=i;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatLogic.cjs.js","names":[],"sources":["../../src/chat/chatLogic.ts"],"sourcesContent":["import { NamedNode, Node, st, term } from 'rdflib'\nimport { ChatLogic, CreatedPaneOptions, NewPaneOptions, Chat } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport { determineChatContainer, newThing } from '../util/utils'\n\nconst CHAT_LOCATION_IN_CONTAINER = 'index.ttl#this'\n\nexport function createChatLogic(store, profileLogic): ChatLogic {\n const ns = namespace\n\n async function setAcl(\n chatContainer: NamedNode,\n me: NamedNode,\n invitee: NamedNode\n ): Promise<void> {\n // Some servers don't present a Link http response header\n // if the container doesn't exist yet, so refetch the container\n // now that it has been created:\n await store.fetcher.load(chatContainer)\n\n // FIXME: check the Why value on this quad:\n const chatAclDoc = store.any(\n chatContainer,\n new NamedNode('http://www.iana.org/assignments/link-relations/acl')\n )\n if (!chatAclDoc) {\n throw new Error('Chat ACL doc not found!')\n }\n\n const aclBody = `\n @prefix acl: <http://www.w3.org/ns/auth/acl#>.\n <#owner>\n a acl:Authorization;\n acl:agent <${me.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Write, acl:Control.\n <#invitee>\n a acl:Authorization;\n acl:agent <${invitee.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Append.\n `\n await store.fetcher.webOperation('PUT', chatAclDoc.value, {\n data: aclBody,\n contentType: 'text/turtle',\n })\n }\n\n async function addToPrivateTypeIndex(chatThing, me) {\n // Add to private type index\n const privateTypeIndex = store.any(\n me,\n ns.solid('privateTypeIndex')\n ) as NamedNode | null\n if (!privateTypeIndex) {\n throw new Error('Private type index not found!')\n }\n await store.fetcher.load(privateTypeIndex)\n const reg = newThing(privateTypeIndex)\n const ins = [\n st(\n reg,\n ns.rdf('type'),\n ns.solid('TypeRegistration'),\n privateTypeIndex.doc()\n ),\n st(\n reg,\n ns.solid('forClass'),\n ns.meeting('LongChat'),\n privateTypeIndex.doc()\n ),\n st(reg, ns.solid('instance'), chatThing, privateTypeIndex.doc()),\n ]\n await new Promise((resolve, reject) => {\n store.updater.update([], ins, function (_uri, ok, errm) {\n if (!ok) {\n reject(new Error(errm))\n } else {\n resolve(null)\n }\n })\n })\n }\n\n async function findChat(invitee: NamedNode): Promise<Chat> {\n const me = await profileLogic.loadMe()\n const podRoot = await profileLogic.getPodRoot(me)\n const chatContainer = determineChatContainer(invitee, podRoot)\n let exists = true\n try {\n await store.fetcher.load(\n new NamedNode(chatContainer.value + 'index.ttl#this')\n )\n } catch (e) {\n exists = false\n }\n return { me, chatContainer, exists }\n }\n\n async function createChatThing(\n chatContainer: NamedNode,\n me: NamedNode\n ): Promise<NamedNode> {\n const created = await mintNew({\n me,\n newBase: chatContainer.value,\n })\n return created.newInstance\n }\n\n function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {\n const kb = store\n const updater = kb.updater\n if (newPaneOptions.me && !newPaneOptions.me.uri) {\n throw new Error('chat mintNew: Invalid userid ' + newPaneOptions.me)\n }\n\n const newInstance = (newPaneOptions.newInstance =\n newPaneOptions.newInstance ||\n kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER))\n const newChatDoc = newInstance.doc()\n\n kb.add(\n newInstance,\n ns.rdf('type'),\n ns.meeting('LongChat'),\n newChatDoc\n )\n kb.add(newInstance, ns.dc('title'), 'Chat channel', newChatDoc)\n kb.add(\n newInstance,\n ns.dc('created'),\n term<Node>(new Date(Date.now())),\n newChatDoc\n )\n if (newPaneOptions.me) {\n kb.add(newInstance, ns.dc('author'), newPaneOptions.me, newChatDoc)\n }\n\n return new Promise(function (resolve, reject) {\n updater?.put(\n newChatDoc,\n kb.statementsMatching(undefined, undefined, undefined, newChatDoc),\n 'text/turtle',\n function (uri2, ok, message) {\n if (ok) {\n resolve({\n ...newPaneOptions,\n newInstance,\n })\n } else {\n reject(\n new Error(\n 'FAILED to save new chat channel at: ' + uri2 + ' : ' + message\n )\n )\n }\n }\n )\n })\n }\n\n /**\n * Find (and optionally create) an individual chat between the current user and the given invitee\n * @param invitee - The person to chat with\n * @param createIfMissing - Whether the chat should be created, if missing\n * @returns null if missing, or a node referring to an already existing chat, or the newly created chat\n */\n async function getChat(\n invitee: NamedNode,\n createIfMissing = true\n ): Promise<NamedNode | null> {\n const { me, chatContainer, exists } = await findChat(invitee)\n if (exists) {\n return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER)\n }\n\n if (createIfMissing) {\n const chatThing = await createChatThing(chatContainer, me)\n await sendInvite(invitee, chatThing)\n await setAcl(chatContainer, me, invitee)\n await addToPrivateTypeIndex(chatThing, me)\n return chatThing\n }\n return null\n }\n\n async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {\n await store.fetcher.load(invitee.doc())\n const inviteeInbox = store.any(\n invitee,\n ns.ldp('inbox'),\n undefined,\n invitee.doc()\n )\n if (!inviteeInbox) {\n throw new Error(`Invitee inbox not found! ${invitee.value}`)\n }\n const inviteBody = `\n <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;\n ${ns.rdf('seeAlso')} <${chatThing.value}> .\n `\n\n const inviteResponse = await store.fetcher?.webOperation(\n 'POST',\n inviteeInbox.value,\n {\n data: inviteBody,\n contentType: 'text/turtle',\n }\n )\n const locationStr = inviteResponse?.headers.get('location')\n if (!locationStr) {\n throw new Error(`Invite sending returned a ${inviteResponse?.status}`)\n }\n }\n return {\n setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chatLogic.cjs.js","names":[],"sources":["../../src/chat/chatLogic.ts"],"sourcesContent":["import { NamedNode, Node, st, term } from 'rdflib'\nimport { ChatLogic, CreatedPaneOptions, NewPaneOptions, Chat } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport { determineChatContainer, newThing } from '../util/utils'\n\nconst CHAT_LOCATION_IN_CONTAINER = 'index.ttl#this'\n\nexport function createChatLogic(store, profileLogic): ChatLogic {\n const ns = namespace\n\n async function setAcl(\n chatContainer: NamedNode,\n me: NamedNode,\n invitee: NamedNode\n ): Promise<void> {\n // Some servers don't present a Link http response header\n // if the container doesn't exist yet, so refetch the container\n // now that it has been created:\n await store.fetcher.load(chatContainer)\n\n // FIXME: check the Why value on this quad:\n const chatAclDoc = store.any(\n chatContainer,\n new NamedNode('http://www.iana.org/assignments/link-relations/acl')\n )\n if (!chatAclDoc) {\n throw new Error('Chat ACL doc not found!')\n }\n\n const aclBody = `\n @prefix acl: <http://www.w3.org/ns/auth/acl#>.\n <#owner>\n a acl:Authorization;\n acl:agent <${me.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Write, acl:Control.\n <#invitee>\n a acl:Authorization;\n acl:agent <${invitee.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Append.\n `\n await store.fetcher.webOperation('PUT', chatAclDoc.value, {\n data: aclBody,\n contentType: 'text/turtle',\n })\n }\n\n async function addToPrivateTypeIndex(chatThing, me) {\n // Add to private type index\n const privateTypeIndex = store.any(\n me,\n ns.solid('privateTypeIndex')\n ) as NamedNode | null\n if (!privateTypeIndex) {\n throw new Error('Private type index not found!')\n }\n await store.fetcher.load(privateTypeIndex)\n const reg = newThing(privateTypeIndex)\n const ins = [\n st(\n reg,\n ns.rdf('type'),\n ns.solid('TypeRegistration'),\n privateTypeIndex.doc()\n ),\n st(\n reg,\n ns.solid('forClass'),\n ns.meeting('LongChat'),\n privateTypeIndex.doc()\n ),\n st(reg, ns.solid('instance'), chatThing, privateTypeIndex.doc()),\n ]\n await new Promise((resolve, reject) => {\n store.updater.update([], ins, function (_uri, ok, errm) {\n if (!ok) {\n reject(new Error(errm))\n } else {\n resolve(null)\n }\n })\n })\n }\n\n async function findChat(invitee: NamedNode): Promise<Chat> {\n const me = await profileLogic.loadMe()\n const podRoot = await profileLogic.getPodRoot(me)\n const chatContainer = determineChatContainer(invitee, podRoot)\n let exists = true\n try {\n await store.fetcher.load(\n new NamedNode(chatContainer.value + 'index.ttl#this')\n )\n } catch (e) {\n exists = false\n }\n return { me, chatContainer, exists }\n }\n\n async function createChatThing(\n chatContainer: NamedNode,\n me: NamedNode\n ): Promise<NamedNode> {\n const created = await mintNew({\n me,\n newBase: chatContainer.value,\n })\n return created.newInstance\n }\n\n function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {\n const kb = store\n const updater = kb.updater\n if (newPaneOptions.me && !newPaneOptions.me.uri) {\n throw new Error('chat mintNew: Invalid userid ' + newPaneOptions.me)\n }\n\n const newInstance = (newPaneOptions.newInstance =\n newPaneOptions.newInstance ||\n kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER))\n const newChatDoc = newInstance.doc()\n\n kb.add(\n newInstance,\n ns.rdf('type'),\n ns.meeting('LongChat'),\n newChatDoc\n )\n kb.add(newInstance, ns.dc('title'), 'Chat channel', newChatDoc)\n kb.add(\n newInstance,\n ns.dc('created'),\n term<Node>(new Date(Date.now())),\n newChatDoc\n )\n if (newPaneOptions.me) {\n kb.add(newInstance, ns.dc('author'), newPaneOptions.me, newChatDoc)\n }\n\n return new Promise(function (resolve, reject) {\n updater?.put(\n newChatDoc,\n kb.statementsMatching(undefined, undefined, undefined, newChatDoc),\n 'text/turtle',\n function (uri2, ok, message) {\n if (ok) {\n resolve({\n ...newPaneOptions,\n newInstance,\n })\n } else {\n reject(\n new Error(\n 'FAILED to save new chat channel at: ' + uri2 + ' : ' + message\n )\n )\n }\n }\n )\n })\n }\n\n /**\n * Find (and optionally create) an individual chat between the current user and the given invitee\n * @param invitee - The person to chat with\n * @param createIfMissing - Whether the chat should be created, if missing\n * @returns null if missing, or a node referring to an already existing chat, or the newly created chat\n */\n async function getChat(\n invitee: NamedNode,\n createIfMissing = true\n ): Promise<NamedNode | null> {\n const { me, chatContainer, exists } = await findChat(invitee)\n if (exists) {\n return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER)\n }\n\n if (createIfMissing) {\n const chatThing = await createChatThing(chatContainer, me)\n await sendInvite(invitee, chatThing)\n await setAcl(chatContainer, me, invitee)\n await addToPrivateTypeIndex(chatThing, me)\n return chatThing\n }\n return null\n }\n\n async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {\n await store.fetcher.load(invitee.doc())\n const inviteeInbox = store.any(\n invitee,\n ns.ldp('inbox'),\n undefined,\n invitee.doc()\n )\n if (!inviteeInbox) {\n throw new Error(`Invitee inbox not found! ${invitee.value}`)\n }\n const inviteBody = `\n <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;\n ${ns.rdf('seeAlso')} <${chatThing.value}> .\n `\n\n const inviteResponse = await store.fetcher?.webOperation(\n 'POST',\n inviteeInbox.value,\n {\n data: inviteBody,\n contentType: 'text/turtle',\n }\n )\n const locationStr = inviteResponse?.headers.get('location')\n if (!locationStr) {\n throw new Error(`Invite sending returned a ${inviteResponse?.status}`)\n }\n }\n return {\n setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatLogic.d.ts","sourceRoot":"","sources":["../../src/chat/chatLogic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAA4C,MAAM,UAAU,CAAA;AAM9E,wBAAgB,eAAe,CAAC,KAAK,KAAA,EAAE,YAAY,KAAA,GAAG,SAAS,CAyN9D"}
|
|
@@ -47,16 +47,16 @@ function s(s, c) {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
async function f(e) {
|
|
50
|
-
let n = await c.loadMe(), i =
|
|
50
|
+
let n = await c.loadMe(), i = await c.getPodRoot(n), a = t(e, i), o = !0;
|
|
51
51
|
try {
|
|
52
|
-
await s.fetcher.load(new r(
|
|
52
|
+
await s.fetcher.load(new r(a.value + "index.ttl#this"));
|
|
53
53
|
} catch {
|
|
54
|
-
|
|
54
|
+
o = !1;
|
|
55
55
|
}
|
|
56
56
|
return {
|
|
57
57
|
me: n,
|
|
58
|
-
chatContainer:
|
|
59
|
-
exists:
|
|
58
|
+
chatContainer: a,
|
|
59
|
+
exists: o
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
async function p(e, t) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chatLogic.esm.js","names":[],"sources":["../../src/chat/chatLogic.ts"],"sourcesContent":["import { NamedNode, Node, st, term } from 'rdflib'\nimport { ChatLogic, CreatedPaneOptions, NewPaneOptions, Chat } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport { determineChatContainer, newThing } from '../util/utils'\n\nconst CHAT_LOCATION_IN_CONTAINER = 'index.ttl#this'\n\nexport function createChatLogic(store, profileLogic): ChatLogic {\n const ns = namespace\n\n async function setAcl(\n chatContainer: NamedNode,\n me: NamedNode,\n invitee: NamedNode\n ): Promise<void> {\n // Some servers don't present a Link http response header\n // if the container doesn't exist yet, so refetch the container\n // now that it has been created:\n await store.fetcher.load(chatContainer)\n\n // FIXME: check the Why value on this quad:\n const chatAclDoc = store.any(\n chatContainer,\n new NamedNode('http://www.iana.org/assignments/link-relations/acl')\n )\n if (!chatAclDoc) {\n throw new Error('Chat ACL doc not found!')\n }\n\n const aclBody = `\n @prefix acl: <http://www.w3.org/ns/auth/acl#>.\n <#owner>\n a acl:Authorization;\n acl:agent <${me.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Write, acl:Control.\n <#invitee>\n a acl:Authorization;\n acl:agent <${invitee.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Append.\n `\n await store.fetcher.webOperation('PUT', chatAclDoc.value, {\n data: aclBody,\n contentType: 'text/turtle',\n })\n }\n\n async function addToPrivateTypeIndex(chatThing, me) {\n // Add to private type index\n const privateTypeIndex = store.any(\n me,\n ns.solid('privateTypeIndex')\n ) as NamedNode | null\n if (!privateTypeIndex) {\n throw new Error('Private type index not found!')\n }\n await store.fetcher.load(privateTypeIndex)\n const reg = newThing(privateTypeIndex)\n const ins = [\n st(\n reg,\n ns.rdf('type'),\n ns.solid('TypeRegistration'),\n privateTypeIndex.doc()\n ),\n st(\n reg,\n ns.solid('forClass'),\n ns.meeting('LongChat'),\n privateTypeIndex.doc()\n ),\n st(reg, ns.solid('instance'), chatThing, privateTypeIndex.doc()),\n ]\n await new Promise((resolve, reject) => {\n store.updater.update([], ins, function (_uri, ok, errm) {\n if (!ok) {\n reject(new Error(errm))\n } else {\n resolve(null)\n }\n })\n })\n }\n\n async function findChat(invitee: NamedNode): Promise<Chat> {\n const me = await profileLogic.loadMe()\n const podRoot = await profileLogic.getPodRoot(me)\n const chatContainer = determineChatContainer(invitee, podRoot)\n let exists = true\n try {\n await store.fetcher.load(\n new NamedNode(chatContainer.value + 'index.ttl#this')\n )\n } catch (e) {\n exists = false\n }\n return { me, chatContainer, exists }\n }\n\n async function createChatThing(\n chatContainer: NamedNode,\n me: NamedNode\n ): Promise<NamedNode> {\n const created = await mintNew({\n me,\n newBase: chatContainer.value,\n })\n return created.newInstance\n }\n\n function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {\n const kb = store\n const updater = kb.updater\n if (newPaneOptions.me && !newPaneOptions.me.uri) {\n throw new Error('chat mintNew: Invalid userid ' + newPaneOptions.me)\n }\n\n const newInstance = (newPaneOptions.newInstance =\n newPaneOptions.newInstance ||\n kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER))\n const newChatDoc = newInstance.doc()\n\n kb.add(\n newInstance,\n ns.rdf('type'),\n ns.meeting('LongChat'),\n newChatDoc\n )\n kb.add(newInstance, ns.dc('title'), 'Chat channel', newChatDoc)\n kb.add(\n newInstance,\n ns.dc('created'),\n term<Node>(new Date(Date.now())),\n newChatDoc\n )\n if (newPaneOptions.me) {\n kb.add(newInstance, ns.dc('author'), newPaneOptions.me, newChatDoc)\n }\n\n return new Promise(function (resolve, reject) {\n updater?.put(\n newChatDoc,\n kb.statementsMatching(undefined, undefined, undefined, newChatDoc),\n 'text/turtle',\n function (uri2, ok, message) {\n if (ok) {\n resolve({\n ...newPaneOptions,\n newInstance,\n })\n } else {\n reject(\n new Error(\n 'FAILED to save new chat channel at: ' + uri2 + ' : ' + message\n )\n )\n }\n }\n )\n })\n }\n\n /**\n * Find (and optionally create) an individual chat between the current user and the given invitee\n * @param invitee - The person to chat with\n * @param createIfMissing - Whether the chat should be created, if missing\n * @returns null if missing, or a node referring to an already existing chat, or the newly created chat\n */\n async function getChat(\n invitee: NamedNode,\n createIfMissing = true\n ): Promise<NamedNode | null> {\n const { me, chatContainer, exists } = await findChat(invitee)\n if (exists) {\n return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER)\n }\n\n if (createIfMissing) {\n const chatThing = await createChatThing(chatContainer, me)\n await sendInvite(invitee, chatThing)\n await setAcl(chatContainer, me, invitee)\n await addToPrivateTypeIndex(chatThing, me)\n return chatThing\n }\n return null\n }\n\n async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {\n await store.fetcher.load(invitee.doc())\n const inviteeInbox = store.any(\n invitee,\n ns.ldp('inbox'),\n undefined,\n invitee.doc()\n )\n if (!inviteeInbox) {\n throw new Error(`Invitee inbox not found! ${invitee.value}`)\n }\n const inviteBody = `\n <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;\n ${ns.rdf('seeAlso')} <${chatThing.value}> .\n `\n\n const inviteResponse = await store.fetcher?.webOperation(\n 'POST',\n inviteeInbox.value,\n {\n data: inviteBody,\n contentType: 'text/turtle',\n }\n )\n const locationStr = inviteResponse?.headers.get('location')\n if (!locationStr) {\n throw new Error(`Invite sending returned a ${inviteResponse?.status}`)\n }\n }\n return {\n setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chatLogic.esm.js","names":[],"sources":["../../src/chat/chatLogic.ts"],"sourcesContent":["import { NamedNode, Node, st, term } from 'rdflib'\nimport { ChatLogic, CreatedPaneOptions, NewPaneOptions, Chat } from '../types'\nimport { ns as namespace } from '../util/ns'\nimport { determineChatContainer, newThing } from '../util/utils'\n\nconst CHAT_LOCATION_IN_CONTAINER = 'index.ttl#this'\n\nexport function createChatLogic(store, profileLogic): ChatLogic {\n const ns = namespace\n\n async function setAcl(\n chatContainer: NamedNode,\n me: NamedNode,\n invitee: NamedNode\n ): Promise<void> {\n // Some servers don't present a Link http response header\n // if the container doesn't exist yet, so refetch the container\n // now that it has been created:\n await store.fetcher.load(chatContainer)\n\n // FIXME: check the Why value on this quad:\n const chatAclDoc = store.any(\n chatContainer,\n new NamedNode('http://www.iana.org/assignments/link-relations/acl')\n )\n if (!chatAclDoc) {\n throw new Error('Chat ACL doc not found!')\n }\n\n const aclBody = `\n @prefix acl: <http://www.w3.org/ns/auth/acl#>.\n <#owner>\n a acl:Authorization;\n acl:agent <${me.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Write, acl:Control.\n <#invitee>\n a acl:Authorization;\n acl:agent <${invitee.value}>;\n acl:accessTo <.>;\n acl:default <.>;\n acl:mode\n acl:Read, acl:Append.\n `\n await store.fetcher.webOperation('PUT', chatAclDoc.value, {\n data: aclBody,\n contentType: 'text/turtle',\n })\n }\n\n async function addToPrivateTypeIndex(chatThing, me) {\n // Add to private type index\n const privateTypeIndex = store.any(\n me,\n ns.solid('privateTypeIndex')\n ) as NamedNode | null\n if (!privateTypeIndex) {\n throw new Error('Private type index not found!')\n }\n await store.fetcher.load(privateTypeIndex)\n const reg = newThing(privateTypeIndex)\n const ins = [\n st(\n reg,\n ns.rdf('type'),\n ns.solid('TypeRegistration'),\n privateTypeIndex.doc()\n ),\n st(\n reg,\n ns.solid('forClass'),\n ns.meeting('LongChat'),\n privateTypeIndex.doc()\n ),\n st(reg, ns.solid('instance'), chatThing, privateTypeIndex.doc()),\n ]\n await new Promise((resolve, reject) => {\n store.updater.update([], ins, function (_uri, ok, errm) {\n if (!ok) {\n reject(new Error(errm))\n } else {\n resolve(null)\n }\n })\n })\n }\n\n async function findChat(invitee: NamedNode): Promise<Chat> {\n const me = await profileLogic.loadMe()\n const podRoot = await profileLogic.getPodRoot(me)\n const chatContainer = determineChatContainer(invitee, podRoot)\n let exists = true\n try {\n await store.fetcher.load(\n new NamedNode(chatContainer.value + 'index.ttl#this')\n )\n } catch (e) {\n exists = false\n }\n return { me, chatContainer, exists }\n }\n\n async function createChatThing(\n chatContainer: NamedNode,\n me: NamedNode\n ): Promise<NamedNode> {\n const created = await mintNew({\n me,\n newBase: chatContainer.value,\n })\n return created.newInstance\n }\n\n function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {\n const kb = store\n const updater = kb.updater\n if (newPaneOptions.me && !newPaneOptions.me.uri) {\n throw new Error('chat mintNew: Invalid userid ' + newPaneOptions.me)\n }\n\n const newInstance = (newPaneOptions.newInstance =\n newPaneOptions.newInstance ||\n kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER))\n const newChatDoc = newInstance.doc()\n\n kb.add(\n newInstance,\n ns.rdf('type'),\n ns.meeting('LongChat'),\n newChatDoc\n )\n kb.add(newInstance, ns.dc('title'), 'Chat channel', newChatDoc)\n kb.add(\n newInstance,\n ns.dc('created'),\n term<Node>(new Date(Date.now())),\n newChatDoc\n )\n if (newPaneOptions.me) {\n kb.add(newInstance, ns.dc('author'), newPaneOptions.me, newChatDoc)\n }\n\n return new Promise(function (resolve, reject) {\n updater?.put(\n newChatDoc,\n kb.statementsMatching(undefined, undefined, undefined, newChatDoc),\n 'text/turtle',\n function (uri2, ok, message) {\n if (ok) {\n resolve({\n ...newPaneOptions,\n newInstance,\n })\n } else {\n reject(\n new Error(\n 'FAILED to save new chat channel at: ' + uri2 + ' : ' + message\n )\n )\n }\n }\n )\n })\n }\n\n /**\n * Find (and optionally create) an individual chat between the current user and the given invitee\n * @param invitee - The person to chat with\n * @param createIfMissing - Whether the chat should be created, if missing\n * @returns null if missing, or a node referring to an already existing chat, or the newly created chat\n */\n async function getChat(\n invitee: NamedNode,\n createIfMissing = true\n ): Promise<NamedNode | null> {\n const { me, chatContainer, exists } = await findChat(invitee)\n if (exists) {\n return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER)\n }\n\n if (createIfMissing) {\n const chatThing = await createChatThing(chatContainer, me)\n await sendInvite(invitee, chatThing)\n await setAcl(chatContainer, me, invitee)\n await addToPrivateTypeIndex(chatThing, me)\n return chatThing\n }\n return null\n }\n\n async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {\n await store.fetcher.load(invitee.doc())\n const inviteeInbox = store.any(\n invitee,\n ns.ldp('inbox'),\n undefined,\n invitee.doc()\n )\n if (!inviteeInbox) {\n throw new Error(`Invitee inbox not found! ${invitee.value}`)\n }\n const inviteBody = `\n <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;\n ${ns.rdf('seeAlso')} <${chatThing.value}> .\n `\n\n const inviteResponse = await store.fetcher?.webOperation(\n 'POST',\n inviteeInbox.value,\n {\n data: inviteBody,\n contentType: 'text/turtle',\n }\n )\n const locationStr = inviteResponse?.headers.get('location')\n if (!locationStr) {\n throw new Error(`Invite sending returned a ${inviteResponse?.status}`)\n }\n }\n return {\n setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../util/debug.cjs.js"),t=require("../util/ns.cjs.js"),n=require("./directoryHelpers.cjs.js");let r=require("rdflib");var i=`http://example.org#`;function a(){let a=new Map;async function o(e,t){let n=await s(e);for(let e of n)await t(e)}async function s(t){let n=a.get(t);if(n)return n;let r=c(t).catch(e=>{throw a.delete(t),e});a.set(t,r);try{return await r}catch(t){return e.warn(`[Directory] Error fetching directory catalog:`,t),[]}}async function c(e){if(typeof fetch!=`function`)throw Error(`Fetch API is unavailable`);let a=await fetch(e,{headers:{accept:`text/turtle`}});if(!a.ok)throw Error(`Failed to fetch ${e}: ${a.status}`);let o=await a.text(),s=(0,r.graph)();(0,r.parse)(o,s,e,`text/turtle`);let c=new r.NamedNode(`${i}Person`),l=new r.NamedNode(`${i}webid`),u=new r.NamedNode(`${i}name`),d=new Map,f=s.statementsMatching(void 0,t.ns.rdf(`type`),c);for(let e of f){let t=e.subject,r=s.any(t,l);if(r&&r.termType===`NamedNode`){let e=r.value,i=s.anyValue(t,u);n.isHttpUri(e)&&i&&d.set(e,{kind:`person`,uri:e,label:i,subjectType:`agent`,relationshipLabel:`People`,sources:[`catalog`]})}}return Array.from(d.values())}return{discoverCatalogEntries:o}}exports.createCatalogDirectoryDiscovery=a;
|
|
2
|
+
//# sourceMappingURL=catalogDirectory.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogDirectory.cjs.js","names":[],"sources":["../../src/directory/catalogDirectory.ts"],"sourcesContent":["import { type DirectoryEntry } from '../types'\nimport { graph, type LiveStore, NamedNode, parse } from 'rdflib'\nimport { ns } from '../util/ns'\nimport * as debug from '../util/debug'\nimport { isHttpUri } from './directoryHelpers'\n\nconst CATALOG_VOCAB = 'http://example.org#'\n\nexport function createCatalogDirectoryDiscovery () {\n const catalogEntriesCache = new Map<string, Promise<DirectoryEntry[]>>()\n\n async function discoverCatalogEntries (\n catalogUrl: string,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const entries = await fetchCatalogEntries(catalogUrl)\n for (const entry of entries) {\n await onEntry(entry)\n }\n }\n\n async function fetchCatalogEntries (catalogUrl: string): Promise<DirectoryEntry[]> {\n const cached = catalogEntriesCache.get(catalogUrl)\n if (cached) {\n return cached\n }\n\n const promise = loadCatalogEntries(catalogUrl).catch(error => {\n catalogEntriesCache.delete(catalogUrl)\n throw error\n })\n\n catalogEntriesCache.set(catalogUrl, promise)\n try {\n return await promise\n } catch (error) {\n debug.warn('[Directory] Error fetching directory catalog:', error)\n return []\n }\n }\n\n async function loadCatalogEntries (catalogUrl: string): Promise<DirectoryEntry[]> {\n if (typeof fetch !== 'function') {\n throw new Error('Fetch API is unavailable')\n }\n\n const response = await fetch(catalogUrl, {\n headers: { accept: 'text/turtle' }\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${catalogUrl}: ${response.status}`)\n }\n\n const turtle = await response.text()\n const catalogStore = graph() as LiveStore\n parse(turtle, catalogStore, catalogUrl, 'text/turtle')\n\n const personType = new NamedNode(`${CATALOG_VOCAB}Person`)\n const webIdPredicate = new NamedNode(`${CATALOG_VOCAB}webid`)\n const namePredicate = new NamedNode(`${CATALOG_VOCAB}name`)\n const catalogPeople = new Map<string, DirectoryEntry>()\n\n const statements = catalogStore.statementsMatching(undefined, ns.rdf('type'), personType)\n for (const statement of statements) {\n const subject = statement.subject\n const webIdNode = catalogStore.any(subject, webIdPredicate)\n if (webIdNode && webIdNode.termType === 'NamedNode') {\n const webId = webIdNode.value\n const personName = catalogStore.anyValue(subject, namePredicate)\n if (isHttpUri(webId) && personName) {\n catalogPeople.set(webId, {\n kind: 'person',\n uri: webId,\n label: personName,\n subjectType: 'agent',\n relationshipLabel: 'People',\n sources: ['catalog']\n })\n }\n }\n }\n\n return Array.from(catalogPeople.values())\n }\n\n return {\n discoverCatalogEntries\n }\n}\n"],"mappings":"sIAMA,IAAM,EAAgB,sBAEtB,SAAgB,GAAmC,CACjD,IAAM,EAAsB,IAAI,IAEhC,eAAe,EACb,EACA,EACe,CACf,IAAM,EAAU,MAAM,EAAoB,CAAU,EACpD,IAAK,IAAM,KAAS,EAClB,MAAM,EAAQ,CAAK,CAEvB,CAEA,eAAe,EAAqB,EAA+C,CACjF,IAAM,EAAS,EAAoB,IAAI,CAAU,EACjD,GAAI,EACF,OAAO,EAGT,IAAM,EAAU,EAAmB,CAAU,CAAC,CAAC,MAAM,GAAS,CAE5D,MADA,EAAoB,OAAO,CAAU,EAC/B,CACR,CAAC,EAED,EAAoB,IAAI,EAAY,CAAO,EAC3C,GAAI,CACF,OAAO,MAAM,CACf,OAAS,EAAO,CAEd,OADA,EAAA,KAAW,gDAAiD,CAAK,EAC1D,CAAC,CACV,CACF,CAEA,eAAe,EAAoB,EAA+C,CAChF,GAAI,OAAO,OAAU,WACnB,MAAU,MAAM,0BAA0B,EAG5C,IAAM,EAAW,MAAM,MAAM,EAAY,CACvC,QAAS,CAAE,OAAQ,aAAc,CACnC,CAAC,EAED,GAAI,CAAC,EAAS,GACZ,MAAU,MAAM,mBAAmB,EAAW,IAAI,EAAS,QAAQ,EAGrE,IAAM,EAAS,MAAM,EAAS,KAAK,EAC7B,GAAA,EAAe,EAAA,MAAA,CAAM,GAC3B,EAAA,EAAA,MAAA,CAAM,EAAQ,EAAc,EAAY,aAAa,EAErD,IAAM,EAAa,IAAI,EAAA,UAAU,GAAG,EAAc,OAAO,EACnD,EAAiB,IAAI,EAAA,UAAU,GAAG,EAAc,MAAM,EACtD,EAAgB,IAAI,EAAA,UAAU,GAAG,EAAc,KAAK,EACpD,EAAgB,IAAI,IAEpB,EAAa,EAAa,mBAAmB,IAAA,GAAW,EAAA,GAAG,IAAI,MAAM,EAAG,CAAU,EACxF,IAAK,IAAM,KAAa,EAAY,CAClC,IAAM,EAAU,EAAU,QACpB,EAAY,EAAa,IAAI,EAAS,CAAc,EAC1D,GAAI,GAAa,EAAU,WAAa,YAAa,CACnD,IAAM,EAAQ,EAAU,MAClB,EAAa,EAAa,SAAS,EAAS,CAAa,EAC3D,EAAA,UAAU,CAAK,GAAK,GACtB,EAAc,IAAI,EAAO,CACvB,KAAM,SACN,IAAK,EACL,MAAO,EACP,YAAa,QACb,kBAAmB,SACnB,QAAS,CAAC,SAAS,CACrB,CAAC,CAEL,CACF,CAEA,OAAO,MAAM,KAAK,EAAc,OAAO,CAAC,CAC1C,CAEA,MAAO,CACL,wBACF,CACF"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type DirectoryEntry } from '../types';
|
|
2
|
+
export declare function createCatalogDirectoryDiscovery(): {
|
|
3
|
+
discoverCatalogEntries: (catalogUrl: string, onEntry: (entry: DirectoryEntry) => void | Promise<void>) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
//# sourceMappingURL=catalogDirectory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogDirectory.d.ts","sourceRoot":"","sources":["../../src/directory/catalogDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AAQ9C,wBAAgB,+BAA+B;yCAI/B,MAAM,WACT,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KACvD,OAAO,CAAC,IAAI,CAAC;EA2EjB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { warn as e } from "../util/debug.esm.js";
|
|
2
|
+
import { ns as t } from "../util/ns.esm.js";
|
|
3
|
+
import { isHttpUri as n } from "./directoryHelpers.esm.js";
|
|
4
|
+
import { NamedNode as r, graph as i, parse as a } from "rdflib";
|
|
5
|
+
//#region src/directory/catalogDirectory.ts
|
|
6
|
+
var o = "http://example.org#";
|
|
7
|
+
function s() {
|
|
8
|
+
let s = /* @__PURE__ */ new Map();
|
|
9
|
+
async function c(e, t) {
|
|
10
|
+
let n = await l(e);
|
|
11
|
+
for (let e of n) await t(e);
|
|
12
|
+
}
|
|
13
|
+
async function l(t) {
|
|
14
|
+
let n = s.get(t);
|
|
15
|
+
if (n) return n;
|
|
16
|
+
let r = u(t).catch((e) => {
|
|
17
|
+
throw s.delete(t), e;
|
|
18
|
+
});
|
|
19
|
+
s.set(t, r);
|
|
20
|
+
try {
|
|
21
|
+
return await r;
|
|
22
|
+
} catch (t) {
|
|
23
|
+
return e("[Directory] Error fetching directory catalog:", t), [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function u(e) {
|
|
27
|
+
if (typeof fetch != "function") throw Error("Fetch API is unavailable");
|
|
28
|
+
let s = await fetch(e, { headers: { accept: "text/turtle" } });
|
|
29
|
+
if (!s.ok) throw Error(`Failed to fetch ${e}: ${s.status}`);
|
|
30
|
+
let c = await s.text(), l = i();
|
|
31
|
+
a(c, l, e, "text/turtle");
|
|
32
|
+
let u = new r(`${o}Person`), d = new r(`${o}webid`), f = new r(`${o}name`), p = /* @__PURE__ */ new Map(), m = l.statementsMatching(void 0, t.rdf("type"), u);
|
|
33
|
+
for (let e of m) {
|
|
34
|
+
let t = e.subject, r = l.any(t, d);
|
|
35
|
+
if (r && r.termType === "NamedNode") {
|
|
36
|
+
let e = r.value, i = l.anyValue(t, f);
|
|
37
|
+
n(e) && i && p.set(e, {
|
|
38
|
+
kind: "person",
|
|
39
|
+
uri: e,
|
|
40
|
+
label: i,
|
|
41
|
+
subjectType: "agent",
|
|
42
|
+
relationshipLabel: "People",
|
|
43
|
+
sources: ["catalog"]
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return Array.from(p.values());
|
|
48
|
+
}
|
|
49
|
+
return { discoverCatalogEntries: c };
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { s as createCatalogDirectoryDiscovery };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=catalogDirectory.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogDirectory.esm.js","names":[],"sources":["../../src/directory/catalogDirectory.ts"],"sourcesContent":["import { type DirectoryEntry } from '../types'\nimport { graph, type LiveStore, NamedNode, parse } from 'rdflib'\nimport { ns } from '../util/ns'\nimport * as debug from '../util/debug'\nimport { isHttpUri } from './directoryHelpers'\n\nconst CATALOG_VOCAB = 'http://example.org#'\n\nexport function createCatalogDirectoryDiscovery () {\n const catalogEntriesCache = new Map<string, Promise<DirectoryEntry[]>>()\n\n async function discoverCatalogEntries (\n catalogUrl: string,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const entries = await fetchCatalogEntries(catalogUrl)\n for (const entry of entries) {\n await onEntry(entry)\n }\n }\n\n async function fetchCatalogEntries (catalogUrl: string): Promise<DirectoryEntry[]> {\n const cached = catalogEntriesCache.get(catalogUrl)\n if (cached) {\n return cached\n }\n\n const promise = loadCatalogEntries(catalogUrl).catch(error => {\n catalogEntriesCache.delete(catalogUrl)\n throw error\n })\n\n catalogEntriesCache.set(catalogUrl, promise)\n try {\n return await promise\n } catch (error) {\n debug.warn('[Directory] Error fetching directory catalog:', error)\n return []\n }\n }\n\n async function loadCatalogEntries (catalogUrl: string): Promise<DirectoryEntry[]> {\n if (typeof fetch !== 'function') {\n throw new Error('Fetch API is unavailable')\n }\n\n const response = await fetch(catalogUrl, {\n headers: { accept: 'text/turtle' }\n })\n\n if (!response.ok) {\n throw new Error(`Failed to fetch ${catalogUrl}: ${response.status}`)\n }\n\n const turtle = await response.text()\n const catalogStore = graph() as LiveStore\n parse(turtle, catalogStore, catalogUrl, 'text/turtle')\n\n const personType = new NamedNode(`${CATALOG_VOCAB}Person`)\n const webIdPredicate = new NamedNode(`${CATALOG_VOCAB}webid`)\n const namePredicate = new NamedNode(`${CATALOG_VOCAB}name`)\n const catalogPeople = new Map<string, DirectoryEntry>()\n\n const statements = catalogStore.statementsMatching(undefined, ns.rdf('type'), personType)\n for (const statement of statements) {\n const subject = statement.subject\n const webIdNode = catalogStore.any(subject, webIdPredicate)\n if (webIdNode && webIdNode.termType === 'NamedNode') {\n const webId = webIdNode.value\n const personName = catalogStore.anyValue(subject, namePredicate)\n if (isHttpUri(webId) && personName) {\n catalogPeople.set(webId, {\n kind: 'person',\n uri: webId,\n label: personName,\n subjectType: 'agent',\n relationshipLabel: 'People',\n sources: ['catalog']\n })\n }\n }\n }\n\n return Array.from(catalogPeople.values())\n }\n\n return {\n discoverCatalogEntries\n }\n}\n"],"mappings":";;;;;AAMA,IAAM,IAAgB;AAEtB,SAAgB,IAAmC;CACjD,IAAM,oBAAsB,IAAI,IAAuC;CAEvE,eAAe,EACb,GACA,GACe;EACf,IAAM,IAAU,MAAM,EAAoB,CAAU;EACpD,KAAK,IAAM,KAAS,GAClB,MAAM,EAAQ,CAAK;CAEvB;CAEA,eAAe,EAAqB,GAA+C;EACjF,IAAM,IAAS,EAAoB,IAAI,CAAU;EACjD,IAAI,GACF,OAAO;EAGT,IAAM,IAAU,EAAmB,CAAU,CAAC,CAAC,OAAM,MAAS;GAE5D,MADA,EAAoB,OAAO,CAAU,GAC/B;EACR,CAAC;EAED,EAAoB,IAAI,GAAY,CAAO;EAC3C,IAAI;GACF,OAAO,MAAM;EACf,SAAS,GAAO;GAEd,OADA,EAAW,iDAAiD,CAAK,GAC1D,CAAC;EACV;CACF;CAEA,eAAe,EAAoB,GAA+C;EAChF,IAAI,OAAO,SAAU,YACnB,MAAU,MAAM,0BAA0B;EAG5C,IAAM,IAAW,MAAM,MAAM,GAAY,EACvC,SAAS,EAAE,QAAQ,cAAc,EACnC,CAAC;EAED,IAAI,CAAC,EAAS,IACZ,MAAU,MAAM,mBAAmB,EAAW,IAAI,EAAS,QAAQ;EAGrE,IAAM,IAAS,MAAM,EAAS,KAAK,GAC7B,IAAe,EAAM;EAC3B,EAAM,GAAQ,GAAc,GAAY,aAAa;EAErD,IAAM,IAAa,IAAI,EAAU,GAAG,EAAc,OAAO,GACnD,IAAiB,IAAI,EAAU,GAAG,EAAc,MAAM,GACtD,IAAgB,IAAI,EAAU,GAAG,EAAc,KAAK,GACpD,oBAAgB,IAAI,IAA4B,GAEhD,IAAa,EAAa,mBAAmB,KAAA,GAAW,EAAG,IAAI,MAAM,GAAG,CAAU;EACxF,KAAK,IAAM,KAAa,GAAY;GAClC,IAAM,IAAU,EAAU,SACpB,IAAY,EAAa,IAAI,GAAS,CAAc;GAC1D,IAAI,KAAa,EAAU,aAAa,aAAa;IACnD,IAAM,IAAQ,EAAU,OAClB,IAAa,EAAa,SAAS,GAAS,CAAa;IAC/D,AAAI,EAAU,CAAK,KAAK,KACtB,EAAc,IAAI,GAAO;KACvB,MAAM;KACN,KAAK;KACL,OAAO;KACP,aAAa;KACb,mBAAmB;KACnB,SAAS,CAAC,SAAS;IACrB,CAAC;GAEL;EACF;EAEA,OAAO,MAAM,KAAK,EAAc,OAAO,CAAC;CAC1C;CAEA,OAAO,EACL,0BACF;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../util/ns.cjs.js"),t=require("./directoryHelpers.cjs.js");var n=8;function r(r,i){let a=new Map,o=new Map;async function s(n){let r=a.get(n.value);if(r)return r;let o=(async()=>{let r=await i.loadTypeIndexesFor(n),a=[];for(let t of r){let n=await i.getScopedAppsFromIndex(t,e.ns.vcard(`AddressBook`));a=a.concat(n)}return t.uniqueNamedNodes(a.map(e=>e.instance))})().catch(e=>{throw a.delete(n.value),e});return a.set(n.value,o),o}async function c(n){let i=o.get(n.value);if(i)return i;let a=(async()=>{if(!await t.loadDocumentSilently(r,n))return null;let i=r.each(n,e.ns.vcard(`url`),null,n.doc());for(let e of i){let t=l(e,n.doc());if(t)return t}return null})().catch(e=>{throw o.delete(n.value),e});return o.set(n.value,a),a}function l(n,i){if(!r.holds(n,e.ns.rdf(`type`),e.ns.vcard(`WebID`),i))return null;let a=r.any(n,e.ns.vcard(`value`),null,i)?.value||``;return t.isHttpUri(a)?a:null}async function u(i,a){let o=await s(i);for(let i of o)if(await t.loadDocumentSilently(r,i)){let o=r.any(i,e.ns.vcard(`nameEmailIndex`),null,i.doc());if(o&&await t.loadDocumentSilently(r,o)){let s=r.each(void 0,e.ns.vcard(`inAddressBook`),i,o);for(let i=0;i<s.length;i+=n){let l=s.slice(i,i+n),u=await Promise.all(l.map(async n=>{let i=await c(n);return i?{kind:`person`,uri:i,label:r.anyValue(n,e.ns.vcard(`fn`),null,o)||t.labelForNode(r,n),subjectType:`agent`,relationshipLabel:`Contact`,sources:[`contacts`]}:null}));for(let e of u.filter(e=>!!e))await a(e)}}}}async function d(n,i){let a=await s(n);for(let n of a)if(await t.loadDocumentSilently(r,n)){let a=r.any(n,e.ns.vcard(`groupIndex`),null,n.doc());if(a&&await t.loadDocumentSilently(r,a)){let o=t.uniqueNamedNodes([...r.each(n,e.ns.vcard(`includesGroup`),null,a),...r.each(n,e.ns.vcard(`includesGroup`),null,n.doc())]);for(let e of o)await t.loadDocumentSilently(r,e),await i({kind:`group`,uri:e.value,label:t.labelForNode(r,e),subjectType:`agentGroup`,relationshipLabel:`Group`,sources:[`groups`]})}}}return{discoverAddressBookContacts:u,discoverAddressBookGroups:d}}exports.createContactsDirectoryDiscovery=r;
|
|
2
|
+
//# sourceMappingURL=contactsDirectory.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contactsDirectory.cjs.js","names":[],"sources":["../../src/directory/contactsDirectory.ts"],"sourcesContent":["import { type DirectoryEntry, type DirectorySource, type TypeIndexLogic } from '../types'\nimport { type LiveStore, NamedNode } from 'rdflib'\nimport { ns } from '../util/ns'\nimport { isHttpUri, labelForNode, loadDocumentSilently, uniqueNamedNodes } from './directoryHelpers'\n\nconst CONTACT_CARD_CONCURRENCY = 8\n\nexport function createContactsDirectoryDiscovery (\n store: LiveStore,\n typeIndexLogic: TypeIndexLogic\n) {\n const personalAddressBooksCache = new Map<string, Promise<NamedNode[]>>()\n const contactWebIdCache = new Map<string, Promise<string | null>>()\n\n async function loadPersonalAddressBooks (user: NamedNode): Promise<NamedNode[]> {\n const cached = personalAddressBooksCache.get(user.value)\n if (cached) {\n return cached\n }\n\n const promise = (async () => {\n const scopes = await typeIndexLogic.loadTypeIndexesFor(user)\n let scopedApps = [] as Awaited<ReturnType<TypeIndexLogic['getScopedAppsFromIndex']>>\n\n for (const scope of scopes) {\n const apps = await typeIndexLogic.getScopedAppsFromIndex(scope, ns.vcard('AddressBook'))\n scopedApps = scopedApps.concat(apps)\n }\n\n return uniqueNamedNodes(scopedApps.map(app => app.instance))\n })().catch(error => {\n personalAddressBooksCache.delete(user.value)\n throw error\n })\n\n personalAddressBooksCache.set(user.value, promise)\n return promise\n }\n\n async function webIdForAddressBookContact (contact: NamedNode): Promise<string | null> {\n const cached = contactWebIdCache.get(contact.value)\n if (cached) {\n return cached\n }\n\n const promise = (async () => {\n if (!await loadDocumentSilently(store, contact)) {\n return null\n }\n\n const urlNodes = store.each(contact, ns.vcard('url'), null, contact.doc()) as NamedNode[]\n for (const urlNode of urlNodes) {\n const webId = resolveWebIdFromAddressBookUrlNode(urlNode, contact.doc())\n if (webId) {\n return webId\n }\n }\n\n return null\n })().catch(error => {\n contactWebIdCache.delete(contact.value)\n throw error\n })\n\n contactWebIdCache.set(contact.value, promise)\n return promise\n }\n\n function resolveWebIdFromAddressBookUrlNode (urlNode: NamedNode, doc: NamedNode): string | null {\n if (!store.holds(urlNode, ns.rdf('type'), ns.vcard('WebID'), doc)) {\n return null\n }\n\n const valueNode = store.any(urlNode, ns.vcard('value'), null, doc)\n const webId = valueNode?.value || ''\n return isHttpUri(webId) ? webId : null\n }\n\n async function discoverAddressBookContacts (\n user: NamedNode,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const books = await loadPersonalAddressBooks(user)\n\n for (const book of books) {\n if (await loadDocumentSilently(store, book)) {\n const nameEmailIndex = store.any(book, ns.vcard('nameEmailIndex'), null, book.doc()) as NamedNode | null\n if (nameEmailIndex) {\n if (await loadDocumentSilently(store, nameEmailIndex)) {\n const contacts = store.each(undefined, ns.vcard('inAddressBook'), book, nameEmailIndex) as NamedNode[]\n for (let index = 0; index < contacts.length; index += CONTACT_CARD_CONCURRENCY) {\n const batch = contacts.slice(index, index + CONTACT_CARD_CONCURRENCY)\n const entries = await Promise.all(batch.map(async contact => {\n const webId = await webIdForAddressBookContact(contact)\n if (!webId) {\n return null\n }\n\n return {\n kind: 'person' as const,\n uri: webId,\n label: store.anyValue(contact, ns.vcard('fn'), null, nameEmailIndex) || labelForNode(store, contact),\n subjectType: 'agent' as const,\n relationshipLabel: 'Contact' as const,\n sources: ['contacts'] as DirectorySource[]\n }\n }))\n\n for (const entry of entries.filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))) {\n await onEntry(entry)\n }\n }\n }\n }\n }\n }\n }\n\n async function discoverAddressBookGroups (\n user: NamedNode,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const books = await loadPersonalAddressBooks(user)\n\n for (const book of books) {\n if (await loadDocumentSilently(store, book)) {\n const groupIndex = store.any(book, ns.vcard('groupIndex'), null, book.doc()) as NamedNode | null\n if (groupIndex) {\n if (await loadDocumentSilently(store, groupIndex)) {\n const groups = uniqueNamedNodes([\n ...(store.each(book, ns.vcard('includesGroup'), null, groupIndex) as NamedNode[]),\n ...(store.each(book, ns.vcard('includesGroup'), null, book.doc()) as NamedNode[])\n ])\n\n for (const group of groups) {\n await loadDocumentSilently(store, group)\n\n await onEntry({\n kind: 'group',\n uri: group.value,\n label: labelForNode(store, group),\n subjectType: 'agentGroup',\n relationshipLabel: 'Group',\n sources: ['groups']\n })\n }\n }\n }\n }\n }\n }\n\n return {\n discoverAddressBookContacts,\n discoverAddressBookGroups\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DirectoryEntry, type TypeIndexLogic } from '../types';
|
|
2
|
+
import { type LiveStore, NamedNode } from 'rdflib';
|
|
3
|
+
export declare function createContactsDirectoryDiscovery(store: LiveStore, typeIndexLogic: TypeIndexLogic): {
|
|
4
|
+
discoverAddressBookContacts: (user: NamedNode, onEntry: (entry: DirectoryEntry) => void | Promise<void>) => Promise<void>;
|
|
5
|
+
discoverAddressBookGroups: (user: NamedNode, onEntry: (entry: DirectoryEntry) => void | Promise<void>) => Promise<void>;
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=contactsDirectory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contactsDirectory.d.ts","sourceRoot":"","sources":["../../src/directory/contactsDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAwB,KAAK,cAAc,EAAE,MAAM,UAAU,CAAA;AACzF,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAMlD,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,SAAS,EAChB,cAAc,EAAE,cAAc;wCAsEtB,SAAS,WACN,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KACvD,OAAO,CAAC,IAAI,CAAC;sCAsCR,SAAS,WACN,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KACvD,OAAO,CAAC,IAAI,CAAC;EAmCjB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { ns as e } from "../util/ns.esm.js";
|
|
2
|
+
import { isHttpUri as t, labelForNode as n, loadDocumentSilently as r, uniqueNamedNodes as i } from "./directoryHelpers.esm.js";
|
|
3
|
+
//#region src/directory/contactsDirectory.ts
|
|
4
|
+
var a = 8;
|
|
5
|
+
function o(o, s) {
|
|
6
|
+
let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map();
|
|
7
|
+
async function u(t) {
|
|
8
|
+
let n = c.get(t.value);
|
|
9
|
+
if (n) return n;
|
|
10
|
+
let r = (async () => {
|
|
11
|
+
let n = await s.loadTypeIndexesFor(t), r = [];
|
|
12
|
+
for (let t of n) {
|
|
13
|
+
let n = await s.getScopedAppsFromIndex(t, e.vcard("AddressBook"));
|
|
14
|
+
r = r.concat(n);
|
|
15
|
+
}
|
|
16
|
+
return i(r.map((e) => e.instance));
|
|
17
|
+
})().catch((e) => {
|
|
18
|
+
throw c.delete(t.value), e;
|
|
19
|
+
});
|
|
20
|
+
return c.set(t.value, r), r;
|
|
21
|
+
}
|
|
22
|
+
async function d(t) {
|
|
23
|
+
let n = l.get(t.value);
|
|
24
|
+
if (n) return n;
|
|
25
|
+
let i = (async () => {
|
|
26
|
+
if (!await r(o, t)) return null;
|
|
27
|
+
let n = o.each(t, e.vcard("url"), null, t.doc());
|
|
28
|
+
for (let e of n) {
|
|
29
|
+
let n = f(e, t.doc());
|
|
30
|
+
if (n) return n;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
})().catch((e) => {
|
|
34
|
+
throw l.delete(t.value), e;
|
|
35
|
+
});
|
|
36
|
+
return l.set(t.value, i), i;
|
|
37
|
+
}
|
|
38
|
+
function f(n, r) {
|
|
39
|
+
if (!o.holds(n, e.rdf("type"), e.vcard("WebID"), r)) return null;
|
|
40
|
+
let i = o.any(n, e.vcard("value"), null, r)?.value || "";
|
|
41
|
+
return t(i) ? i : null;
|
|
42
|
+
}
|
|
43
|
+
async function p(t, i) {
|
|
44
|
+
let s = await u(t);
|
|
45
|
+
for (let t of s) if (await r(o, t)) {
|
|
46
|
+
let s = o.any(t, e.vcard("nameEmailIndex"), null, t.doc());
|
|
47
|
+
if (s && await r(o, s)) {
|
|
48
|
+
let r = o.each(void 0, e.vcard("inAddressBook"), t, s);
|
|
49
|
+
for (let t = 0; t < r.length; t += a) {
|
|
50
|
+
let c = r.slice(t, t + a), l = await Promise.all(c.map(async (t) => {
|
|
51
|
+
let r = await d(t);
|
|
52
|
+
return r ? {
|
|
53
|
+
kind: "person",
|
|
54
|
+
uri: r,
|
|
55
|
+
label: o.anyValue(t, e.vcard("fn"), null, s) || n(o, t),
|
|
56
|
+
subjectType: "agent",
|
|
57
|
+
relationshipLabel: "Contact",
|
|
58
|
+
sources: ["contacts"]
|
|
59
|
+
} : null;
|
|
60
|
+
}));
|
|
61
|
+
for (let e of l.filter((e) => !!e)) await i(e);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function m(t, a) {
|
|
67
|
+
let s = await u(t);
|
|
68
|
+
for (let t of s) if (await r(o, t)) {
|
|
69
|
+
let s = o.any(t, e.vcard("groupIndex"), null, t.doc());
|
|
70
|
+
if (s && await r(o, s)) {
|
|
71
|
+
let c = i([...o.each(t, e.vcard("includesGroup"), null, s), ...o.each(t, e.vcard("includesGroup"), null, t.doc())]);
|
|
72
|
+
for (let e of c) await r(o, e), await a({
|
|
73
|
+
kind: "group",
|
|
74
|
+
uri: e.value,
|
|
75
|
+
label: n(o, e),
|
|
76
|
+
subjectType: "agentGroup",
|
|
77
|
+
relationshipLabel: "Group",
|
|
78
|
+
sources: ["groups"]
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
discoverAddressBookContacts: p,
|
|
85
|
+
discoverAddressBookGroups: m
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { o as createContactsDirectoryDiscovery };
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=contactsDirectory.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contactsDirectory.esm.js","names":[],"sources":["../../src/directory/contactsDirectory.ts"],"sourcesContent":["import { type DirectoryEntry, type DirectorySource, type TypeIndexLogic } from '../types'\nimport { type LiveStore, NamedNode } from 'rdflib'\nimport { ns } from '../util/ns'\nimport { isHttpUri, labelForNode, loadDocumentSilently, uniqueNamedNodes } from './directoryHelpers'\n\nconst CONTACT_CARD_CONCURRENCY = 8\n\nexport function createContactsDirectoryDiscovery (\n store: LiveStore,\n typeIndexLogic: TypeIndexLogic\n) {\n const personalAddressBooksCache = new Map<string, Promise<NamedNode[]>>()\n const contactWebIdCache = new Map<string, Promise<string | null>>()\n\n async function loadPersonalAddressBooks (user: NamedNode): Promise<NamedNode[]> {\n const cached = personalAddressBooksCache.get(user.value)\n if (cached) {\n return cached\n }\n\n const promise = (async () => {\n const scopes = await typeIndexLogic.loadTypeIndexesFor(user)\n let scopedApps = [] as Awaited<ReturnType<TypeIndexLogic['getScopedAppsFromIndex']>>\n\n for (const scope of scopes) {\n const apps = await typeIndexLogic.getScopedAppsFromIndex(scope, ns.vcard('AddressBook'))\n scopedApps = scopedApps.concat(apps)\n }\n\n return uniqueNamedNodes(scopedApps.map(app => app.instance))\n })().catch(error => {\n personalAddressBooksCache.delete(user.value)\n throw error\n })\n\n personalAddressBooksCache.set(user.value, promise)\n return promise\n }\n\n async function webIdForAddressBookContact (contact: NamedNode): Promise<string | null> {\n const cached = contactWebIdCache.get(contact.value)\n if (cached) {\n return cached\n }\n\n const promise = (async () => {\n if (!await loadDocumentSilently(store, contact)) {\n return null\n }\n\n const urlNodes = store.each(contact, ns.vcard('url'), null, contact.doc()) as NamedNode[]\n for (const urlNode of urlNodes) {\n const webId = resolveWebIdFromAddressBookUrlNode(urlNode, contact.doc())\n if (webId) {\n return webId\n }\n }\n\n return null\n })().catch(error => {\n contactWebIdCache.delete(contact.value)\n throw error\n })\n\n contactWebIdCache.set(contact.value, promise)\n return promise\n }\n\n function resolveWebIdFromAddressBookUrlNode (urlNode: NamedNode, doc: NamedNode): string | null {\n if (!store.holds(urlNode, ns.rdf('type'), ns.vcard('WebID'), doc)) {\n return null\n }\n\n const valueNode = store.any(urlNode, ns.vcard('value'), null, doc)\n const webId = valueNode?.value || ''\n return isHttpUri(webId) ? webId : null\n }\n\n async function discoverAddressBookContacts (\n user: NamedNode,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const books = await loadPersonalAddressBooks(user)\n\n for (const book of books) {\n if (await loadDocumentSilently(store, book)) {\n const nameEmailIndex = store.any(book, ns.vcard('nameEmailIndex'), null, book.doc()) as NamedNode | null\n if (nameEmailIndex) {\n if (await loadDocumentSilently(store, nameEmailIndex)) {\n const contacts = store.each(undefined, ns.vcard('inAddressBook'), book, nameEmailIndex) as NamedNode[]\n for (let index = 0; index < contacts.length; index += CONTACT_CARD_CONCURRENCY) {\n const batch = contacts.slice(index, index + CONTACT_CARD_CONCURRENCY)\n const entries = await Promise.all(batch.map(async contact => {\n const webId = await webIdForAddressBookContact(contact)\n if (!webId) {\n return null\n }\n\n return {\n kind: 'person' as const,\n uri: webId,\n label: store.anyValue(contact, ns.vcard('fn'), null, nameEmailIndex) || labelForNode(store, contact),\n subjectType: 'agent' as const,\n relationshipLabel: 'Contact' as const,\n sources: ['contacts'] as DirectorySource[]\n }\n }))\n\n for (const entry of entries.filter((entry): entry is NonNullable<typeof entry> => Boolean(entry))) {\n await onEntry(entry)\n }\n }\n }\n }\n }\n }\n }\n\n async function discoverAddressBookGroups (\n user: NamedNode,\n onEntry: (entry: DirectoryEntry) => void | Promise<void>\n ): Promise<void> {\n const books = await loadPersonalAddressBooks(user)\n\n for (const book of books) {\n if (await loadDocumentSilently(store, book)) {\n const groupIndex = store.any(book, ns.vcard('groupIndex'), null, book.doc()) as NamedNode | null\n if (groupIndex) {\n if (await loadDocumentSilently(store, groupIndex)) {\n const groups = uniqueNamedNodes([\n ...(store.each(book, ns.vcard('includesGroup'), null, groupIndex) as NamedNode[]),\n ...(store.each(book, ns.vcard('includesGroup'), null, book.doc()) as NamedNode[])\n ])\n\n for (const group of groups) {\n await loadDocumentSilently(store, group)\n\n await onEntry({\n kind: 'group',\n uri: group.value,\n label: labelForNode(store, group),\n subjectType: 'agentGroup',\n relationshipLabel: 'Group',\n sources: ['groups']\n })\n }\n }\n }\n }\n }\n }\n\n return {\n discoverAddressBookContacts,\n discoverAddressBookGroups\n }\n}\n"],"mappings":";;;AAKA,IAAM,IAA2B;AAEjC,SAAgB,EACd,GACA,GACA;CACA,IAAM,oBAA4B,IAAI,IAAkC,GAClE,oBAAoB,IAAI,IAAoC;CAElE,eAAe,EAA0B,GAAuC;EAC9E,IAAM,IAAS,EAA0B,IAAI,EAAK,KAAK;EACvD,IAAI,GACF,OAAO;EAGT,IAAM,KAAW,YAAY;GAC3B,IAAM,IAAS,MAAM,EAAe,mBAAmB,CAAI,GACvD,IAAa,CAAC;GAElB,KAAK,IAAM,KAAS,GAAQ;IAC1B,IAAM,IAAO,MAAM,EAAe,uBAAuB,GAAO,EAAG,MAAM,aAAa,CAAC;IACvF,IAAa,EAAW,OAAO,CAAI;GACrC;GAEA,OAAO,EAAiB,EAAW,KAAI,MAAO,EAAI,QAAQ,CAAC;EAC7D,EAAA,CAAG,CAAC,CAAC,OAAM,MAAS;GAElB,MADA,EAA0B,OAAO,EAAK,KAAK,GACrC;EACR,CAAC;EAGD,OADA,EAA0B,IAAI,EAAK,OAAO,CAAO,GAC1C;CACT;CAEA,eAAe,EAA4B,GAA4C;EACrF,IAAM,IAAS,EAAkB,IAAI,EAAQ,KAAK;EAClD,IAAI,GACF,OAAO;EAGT,IAAM,KAAW,YAAY;GAC3B,IAAI,CAAC,MAAM,EAAqB,GAAO,CAAO,GAC5C,OAAO;GAGT,IAAM,IAAW,EAAM,KAAK,GAAS,EAAG,MAAM,KAAK,GAAG,MAAM,EAAQ,IAAI,CAAC;GACzE,KAAK,IAAM,KAAW,GAAU;IAC9B,IAAM,IAAQ,EAAmC,GAAS,EAAQ,IAAI,CAAC;IACvE,IAAI,GACF,OAAO;GAEX;GAEA,OAAO;EACT,EAAA,CAAG,CAAC,CAAC,OAAM,MAAS;GAElB,MADA,EAAkB,OAAO,EAAQ,KAAK,GAChC;EACR,CAAC;EAGD,OADA,EAAkB,IAAI,EAAQ,OAAO,CAAO,GACrC;CACT;CAEA,SAAS,EAAoC,GAAoB,GAA+B;EAC9F,IAAI,CAAC,EAAM,MAAM,GAAS,EAAG,IAAI,MAAM,GAAG,EAAG,MAAM,OAAO,GAAG,CAAG,GAC9D,OAAO;EAIT,IAAM,IADY,EAAM,IAAI,GAAS,EAAG,MAAM,OAAO,GAAG,MAAM,CAChD,CAAA,EAAW,SAAS;EAClC,OAAO,EAAU,CAAK,IAAI,IAAQ;CACpC;CAEA,eAAe,EACb,GACA,GACe;EACf,IAAM,IAAQ,MAAM,EAAyB,CAAI;EAEjD,KAAK,IAAM,KAAQ,GACjB,IAAI,MAAM,EAAqB,GAAO,CAAI,GAAG;GAC3C,IAAM,IAAiB,EAAM,IAAI,GAAM,EAAG,MAAM,gBAAgB,GAAG,MAAM,EAAK,IAAI,CAAC;GACnF,IAAI,KACE,MAAM,EAAqB,GAAO,CAAc,GAAG;IACrD,IAAM,IAAW,EAAM,KAAK,KAAA,GAAW,EAAG,MAAM,eAAe,GAAG,GAAM,CAAc;IACtF,KAAK,IAAI,IAAQ,GAAG,IAAQ,EAAS,QAAQ,KAAS,GAA0B;KAC9E,IAAM,IAAQ,EAAS,MAAM,GAAO,IAAQ,CAAwB,GAC9D,IAAU,MAAM,QAAQ,IAAI,EAAM,IAAI,OAAM,MAAW;MAC3D,IAAM,IAAQ,MAAM,EAA2B,CAAO;MAKtD,OAJK,IAIE;OACL,MAAM;OACN,KAAK;OACL,OAAO,EAAM,SAAS,GAAS,EAAG,MAAM,IAAI,GAAG,MAAM,CAAc,KAAK,EAAa,GAAO,CAAO;OACnG,aAAa;OACb,mBAAmB;OACnB,SAAS,CAAC,UAAU;MACtB,IAVS;KAWX,CAAC,CAAC;KAEF,KAAK,IAAM,KAAS,EAAQ,QAAQ,MAA8C,EAAQ,CAAM,GAC9F,MAAM,EAAQ,CAAK;IAEvB;GACF;EAEJ;CAEJ;CAEA,eAAe,EACb,GACA,GACe;EACf,IAAM,IAAQ,MAAM,EAAyB,CAAI;EAEjD,KAAK,IAAM,KAAQ,GACjB,IAAI,MAAM,EAAqB,GAAO,CAAI,GAAG;GAC3C,IAAM,IAAa,EAAM,IAAI,GAAM,EAAG,MAAM,YAAY,GAAG,MAAM,EAAK,IAAI,CAAC;GAC3E,IAAI,KACE,MAAM,EAAqB,GAAO,CAAU,GAAG;IACjD,IAAM,IAAS,EAAiB,CAC9B,GAAI,EAAM,KAAK,GAAM,EAAG,MAAM,eAAe,GAAG,MAAM,CAAU,GAChE,GAAI,EAAM,KAAK,GAAM,EAAG,MAAM,eAAe,GAAG,MAAM,EAAK,IAAI,CAAC,CAClE,CAAC;IAED,KAAK,IAAM,KAAS,GAGlB,AAFA,MAAM,EAAqB,GAAO,CAAK,GAEvC,MAAM,EAAQ;KACZ,MAAM;KACN,KAAK,EAAM;KACX,OAAO,EAAa,GAAO,CAAK;KAChC,aAAa;KACb,mBAAmB;KACnB,SAAS,CAAC,QAAQ;IACpB,CAAC;GAEL;EAEJ;CAEJ;CAEA,OAAO;EACL;EACA;CACF;AACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../util/ns.cjs.js");var t=[`contacts`,`groups`,`friends`,`catalog`];function n(e){return e.toLowerCase().trim().split(/\s+/).filter(Boolean)}function r(e,t){let r=n(t);if(r.length===0)return!0;let i=e.flatMap(e=>n(e)),a=e.join(` `).toLowerCase();return r.every(e=>i.some(t=>t.includes(e))||a.includes(e))}function i(e){return Array.from(e).sort((e,t)=>e.label.localeCompare(t.label,void 0,{sensitivity:`base`}))}function a(e,t){let n=d(t),r=e.get(n);if(r){let i=o(r,t),a=l(i.label,[...r.searchableLabels??[r.label],...t.searchableLabels??[t.label]]),s={...r,label:i.label,relationshipLabel:u(r.relationshipLabel,t.relationshipLabel),sources:c([...r.sources,...t.sources]),searchableLabels:a};return e.set(n,s),s}let i={...t,sources:c(t.sources),searchableLabels:t.searchableLabels??[t.label]};return e.set(n,i),i}function o(e,t){return s(t)<s(e)?t:e}function s(e){let n=e.sources.map(e=>t.indexOf(e));return n.length?Math.min(...n):t.length}function c(e){return t.filter(t=>e.includes(t))}function l(e,t){return p(t).sort((t,n)=>t===e?-1:n===e?1:t.localeCompare(n,void 0,{sensitivity:`base`}))}function u(e,t){return e===`Contact`||t===`Contact`?`Contact`:e===`Friend`||t===`Friend`?`Friend`:e===`Group`||t===`Group`?`Group`:`People`}function d(e){return`${e.kind}:${e.uri}`}function f(e){let t=new Set;return e.filter(e=>!t.has(e.value)&&(t.add(e.value),!0))}function p(e){return[...new Set(e)]}function m(e){return!!e&&(e.startsWith(`https://`)||e.startsWith(`http://`))}function h(e){let t=e.split(`#`)[0],n=e.includes(`#`)?e.slice(e.indexOf(`#`)+1):``,r=n&&n!==`this`&&n!==`me`?n:t.slice(t.lastIndexOf(`/`)+1);return decodeURIComponent(r||e).replace(/[_-]+/g,` `)}function g(t,n){return t.anyValue(n,e.ns.vcard(`fn`))||t.anyValue(n,e.ns.foaf(`name`))||t.anyValue(n,e.ns.schema(`name`))||t.anyValue(n,e.ns.rdfs(`label`))||null}function _(e,t){return g(e,t)||h(t.value)}async function v(e,t){try{return await e.fetcher.load(t.doc()),!0}catch{return!1}}exports.bestRelationshipLabel=u,exports.canonicalizeDirectorySources=c,exports.directoryEntryKey=d,exports.fallbackLabel=h,exports.isHttpUri=m,exports.labelForNode=_,exports.loadDocumentSilently=v,exports.matchesAnyLabel=r,exports.mergeDirectoryEntry=a,exports.sortEntries=i,exports.storedLabelForNode=g,exports.tokenizeQuery=n,exports.uniqueNamedNodes=f,exports.uniqueStrings=p;
|
|
2
|
+
//# sourceMappingURL=directoryHelpers.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directoryHelpers.cjs.js","names":[],"sources":["../../src/directory/directoryHelpers.ts"],"sourcesContent":["import type { LiveStore, NamedNode } from 'rdflib'\nimport type { DirectoryEntry, DirectoryRelationshipLabel, DirectorySource } from '../types'\nimport { ns } from '../util/ns'\n\nconst DIRECTORY_SOURCE_PRIORITY: DirectorySource[] = ['contacts', 'groups', 'friends', 'catalog']\n\nexport function tokenizeQuery (query: string): string[] {\n return query\n .toLowerCase()\n .trim()\n .split(/\\s+/)\n .filter(Boolean)\n}\n\nexport function matchesQuery (label: string, query: string): boolean {\n return matchesAnyLabel([label], query)\n}\n\nexport function matchesAnyLabel (labels: string[], query: string): boolean {\n const queryWords = tokenizeQuery(query)\n if (queryWords.length === 0) return true\n\n const labelWords = labels.flatMap(label => tokenizeQuery(label))\n const fallbackHaystack = labels.join(' ').toLowerCase()\n return queryWords.every(word =>\n labelWords.some(labelWord => labelWord.includes(word)) || fallbackHaystack.includes(word)\n )\n}\n\nexport function sortEntries (entries: Iterable<DirectoryEntry>): DirectoryEntry[] {\n return Array.from(entries)\n .sort((left, right) => left.label.localeCompare(right.label, undefined, { sensitivity: 'base' }))\n}\n\nexport function mergeDirectoryEntry (\n discoveredEntries: Map<string, DirectoryEntry>,\n entry: DirectoryEntry\n): DirectoryEntry {\n const key = directoryEntryKey(entry)\n const existing = discoveredEntries.get(key)\n if (existing) {\n const preferred = preferredDirectoryEntry(existing, entry)\n const labels = canonicalizeSearchableLabels(\n preferred.label,\n [...(existing.searchableLabels ?? [existing.label]), ...(entry.searchableLabels ?? [entry.label])]\n )\n const merged = {\n ...existing,\n label: preferred.label,\n relationshipLabel: bestRelationshipLabel(existing.relationshipLabel, entry.relationshipLabel),\n sources: canonicalizeDirectorySources([...existing.sources, ...entry.sources]),\n searchableLabels: labels\n }\n discoveredEntries.set(key, merged)\n return merged\n }\n\n const normalized = {\n ...entry,\n sources: canonicalizeDirectorySources(entry.sources),\n searchableLabels: entry.searchableLabels ?? [entry.label]\n }\n discoveredEntries.set(key, normalized)\n return normalized\n}\n\nfunction preferredDirectoryEntry (current: DirectoryEntry, incoming: DirectoryEntry): DirectoryEntry {\n return directoryEntrySourcePriority(incoming) < directoryEntrySourcePriority(current) ? incoming : current\n}\n\nfunction directoryEntrySourcePriority (entry: DirectoryEntry): number {\n const priorities = entry.sources.map(source => DIRECTORY_SOURCE_PRIORITY.indexOf(source))\n return priorities.length ? Math.min(...priorities) : DIRECTORY_SOURCE_PRIORITY.length\n}\n\nexport function canonicalizeDirectorySources (sources: DirectorySource[]): DirectorySource[] {\n return DIRECTORY_SOURCE_PRIORITY.filter(source => sources.includes(source))\n}\n\nfunction canonicalizeSearchableLabels (preferredLabel: string, labels: string[]): string[] {\n return uniqueStrings(labels).sort((left, right) => {\n if (left === preferredLabel) return -1\n if (right === preferredLabel) return 1\n return left.localeCompare(right, undefined, { sensitivity: 'base' })\n })\n}\n\nexport function bestRelationshipLabel (\n current: DirectoryRelationshipLabel | undefined,\n incoming: DirectoryRelationshipLabel\n): DirectoryRelationshipLabel {\n if (current === 'Contact' || incoming === 'Contact') return 'Contact'\n if (current === 'Friend' || incoming === 'Friend') return 'Friend'\n if (current === 'Group' || incoming === 'Group') return 'Group'\n return 'People'\n}\n\nexport function directoryEntryKey (entry: DirectoryEntry): string {\n return `${entry.kind}:${entry.uri}`\n}\n\nexport function uniqueNamedNodes (nodes: NamedNode[]): NamedNode[] {\n const seen = new Set<string>()\n return nodes.filter(node => {\n if (seen.has(node.value)) return false\n seen.add(node.value)\n return true\n })\n}\n\nexport function uniqueStrings<T extends string> (values: T[]): T[] {\n return [...new Set(values)]\n}\n\nexport function isHttpUri (value: string | null | undefined): boolean {\n return !!value && (value.startsWith('https://') || value.startsWith('http://'))\n}\n\nexport function fallbackLabel (uri: string): string {\n const withoutFragment = uri.split('#')[0]\n const fragment = uri.includes('#') ? uri.slice(uri.indexOf('#') + 1) : ''\n const base = fragment && fragment !== 'this' && fragment !== 'me'\n ? fragment\n : withoutFragment.slice(withoutFragment.lastIndexOf('/') + 1)\n return decodeURIComponent(base || uri).replace(/[_-]+/g, ' ')\n}\n\nexport function storedLabelForNode (store: LiveStore, node: NamedNode): string | null {\n return store.anyValue(node, ns.vcard('fn')) ||\n store.anyValue(node, ns.foaf('name')) ||\n store.anyValue(node, ns.schema('name')) ||\n store.anyValue(node, ns.rdfs('label')) ||\n null\n}\n\nexport function labelForNode (store: LiveStore, node: NamedNode): string {\n return storedLabelForNode(store, node) || fallbackLabel(node.value)\n}\n\nexport async function loadDocumentSilently (store: LiveStore, node: NamedNode): Promise<boolean> {\n try {\n await store.fetcher.load(node.doc())\n return true\n } catch (_error) {\n return false\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LiveStore, NamedNode } from 'rdflib';
|
|
2
|
+
import type { DirectoryEntry, DirectoryRelationshipLabel, DirectorySource } from '../types';
|
|
3
|
+
export declare function tokenizeQuery(query: string): string[];
|
|
4
|
+
export declare function matchesQuery(label: string, query: string): boolean;
|
|
5
|
+
export declare function matchesAnyLabel(labels: string[], query: string): boolean;
|
|
6
|
+
export declare function sortEntries(entries: Iterable<DirectoryEntry>): DirectoryEntry[];
|
|
7
|
+
export declare function mergeDirectoryEntry(discoveredEntries: Map<string, DirectoryEntry>, entry: DirectoryEntry): DirectoryEntry;
|
|
8
|
+
export declare function canonicalizeDirectorySources(sources: DirectorySource[]): DirectorySource[];
|
|
9
|
+
export declare function bestRelationshipLabel(current: DirectoryRelationshipLabel | undefined, incoming: DirectoryRelationshipLabel): DirectoryRelationshipLabel;
|
|
10
|
+
export declare function directoryEntryKey(entry: DirectoryEntry): string;
|
|
11
|
+
export declare function uniqueNamedNodes(nodes: NamedNode[]): NamedNode[];
|
|
12
|
+
export declare function uniqueStrings<T extends string>(values: T[]): T[];
|
|
13
|
+
export declare function isHttpUri(value: string | null | undefined): boolean;
|
|
14
|
+
export declare function fallbackLabel(uri: string): string;
|
|
15
|
+
export declare function storedLabelForNode(store: LiveStore, node: NamedNode): string | null;
|
|
16
|
+
export declare function labelForNode(store: LiveStore, node: NamedNode): string;
|
|
17
|
+
export declare function loadDocumentSilently(store: LiveStore, node: NamedNode): Promise<boolean>;
|
|
18
|
+
//# sourceMappingURL=directoryHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directoryHelpers.d.ts","sourceRoot":"","sources":["../../src/directory/directoryHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAK3F,wBAAgB,aAAa,CAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAMtD;AAED,wBAAgB,YAAY,CAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnE;AAED,wBAAgB,eAAe,CAAE,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CASzE;AAED,wBAAgB,WAAW,CAAE,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG,cAAc,EAAE,CAGhF;AAED,wBAAgB,mBAAmB,CACjC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EAC9C,KAAK,EAAE,cAAc,GACpB,cAAc,CA2BhB;AAWD,wBAAgB,4BAA4B,CAAE,OAAO,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAE3F;AAUD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,0BAA0B,GAAG,SAAS,EAC/C,QAAQ,EAAE,0BAA0B,GACnC,0BAA0B,CAK5B;AAED,wBAAgB,iBAAiB,CAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAEhE;AAED,wBAAgB,gBAAgB,CAAE,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAOjE;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAG,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEjE;AAED,wBAAgB,SAAS,CAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAEpE;AAED,wBAAgB,aAAa,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED,wBAAgB,kBAAkB,CAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAMpF;AAED,wBAAgB,YAAY,CAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,CAEvE;AAED,wBAAsB,oBAAoB,CAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAO/F"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ns as e } from "../util/ns.esm.js";
|
|
2
|
+
//#region src/directory/directoryHelpers.ts
|
|
3
|
+
var t = [
|
|
4
|
+
"contacts",
|
|
5
|
+
"groups",
|
|
6
|
+
"friends",
|
|
7
|
+
"catalog"
|
|
8
|
+
];
|
|
9
|
+
function n(e) {
|
|
10
|
+
return e.toLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
11
|
+
}
|
|
12
|
+
function r(e, t) {
|
|
13
|
+
let r = n(t);
|
|
14
|
+
if (r.length === 0) return !0;
|
|
15
|
+
let i = e.flatMap((e) => n(e)), a = e.join(" ").toLowerCase();
|
|
16
|
+
return r.every((e) => i.some((t) => t.includes(e)) || a.includes(e));
|
|
17
|
+
}
|
|
18
|
+
function i(e) {
|
|
19
|
+
return Array.from(e).sort((e, t) => e.label.localeCompare(t.label, void 0, { sensitivity: "base" }));
|
|
20
|
+
}
|
|
21
|
+
function a(e, t) {
|
|
22
|
+
let n = d(t), r = e.get(n);
|
|
23
|
+
if (r) {
|
|
24
|
+
let i = o(r, t), a = l(i.label, [...r.searchableLabels ?? [r.label], ...t.searchableLabels ?? [t.label]]), s = {
|
|
25
|
+
...r,
|
|
26
|
+
label: i.label,
|
|
27
|
+
relationshipLabel: u(r.relationshipLabel, t.relationshipLabel),
|
|
28
|
+
sources: c([...r.sources, ...t.sources]),
|
|
29
|
+
searchableLabels: a
|
|
30
|
+
};
|
|
31
|
+
return e.set(n, s), s;
|
|
32
|
+
}
|
|
33
|
+
let i = {
|
|
34
|
+
...t,
|
|
35
|
+
sources: c(t.sources),
|
|
36
|
+
searchableLabels: t.searchableLabels ?? [t.label]
|
|
37
|
+
};
|
|
38
|
+
return e.set(n, i), i;
|
|
39
|
+
}
|
|
40
|
+
function o(e, t) {
|
|
41
|
+
return s(t) < s(e) ? t : e;
|
|
42
|
+
}
|
|
43
|
+
function s(e) {
|
|
44
|
+
let n = e.sources.map((e) => t.indexOf(e));
|
|
45
|
+
return n.length ? Math.min(...n) : t.length;
|
|
46
|
+
}
|
|
47
|
+
function c(e) {
|
|
48
|
+
return t.filter((t) => e.includes(t));
|
|
49
|
+
}
|
|
50
|
+
function l(e, t) {
|
|
51
|
+
return p(t).sort((t, n) => t === e ? -1 : n === e ? 1 : t.localeCompare(n, void 0, { sensitivity: "base" }));
|
|
52
|
+
}
|
|
53
|
+
function u(e, t) {
|
|
54
|
+
return e === "Contact" || t === "Contact" ? "Contact" : e === "Friend" || t === "Friend" ? "Friend" : e === "Group" || t === "Group" ? "Group" : "People";
|
|
55
|
+
}
|
|
56
|
+
function d(e) {
|
|
57
|
+
return `${e.kind}:${e.uri}`;
|
|
58
|
+
}
|
|
59
|
+
function f(e) {
|
|
60
|
+
let t = /* @__PURE__ */ new Set();
|
|
61
|
+
return e.filter((e) => !t.has(e.value) && (t.add(e.value), !0));
|
|
62
|
+
}
|
|
63
|
+
function p(e) {
|
|
64
|
+
return [...new Set(e)];
|
|
65
|
+
}
|
|
66
|
+
function m(e) {
|
|
67
|
+
return !!e && (e.startsWith("https://") || e.startsWith("http://"));
|
|
68
|
+
}
|
|
69
|
+
function h(e) {
|
|
70
|
+
let t = e.split("#")[0], n = e.includes("#") ? e.slice(e.indexOf("#") + 1) : "", r = n && n !== "this" && n !== "me" ? n : t.slice(t.lastIndexOf("/") + 1);
|
|
71
|
+
return decodeURIComponent(r || e).replace(/[_-]+/g, " ");
|
|
72
|
+
}
|
|
73
|
+
function g(t, n) {
|
|
74
|
+
return t.anyValue(n, e.vcard("fn")) || t.anyValue(n, e.foaf("name")) || t.anyValue(n, e.schema("name")) || t.anyValue(n, e.rdfs("label")) || null;
|
|
75
|
+
}
|
|
76
|
+
function _(e, t) {
|
|
77
|
+
return g(e, t) || h(t.value);
|
|
78
|
+
}
|
|
79
|
+
async function v(e, t) {
|
|
80
|
+
try {
|
|
81
|
+
return await e.fetcher.load(t.doc()), !0;
|
|
82
|
+
} catch {
|
|
83
|
+
return !1;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { u as bestRelationshipLabel, c as canonicalizeDirectorySources, d as directoryEntryKey, h as fallbackLabel, m as isHttpUri, _ as labelForNode, v as loadDocumentSilently, r as matchesAnyLabel, a as mergeDirectoryEntry, i as sortEntries, g as storedLabelForNode, n as tokenizeQuery, f as uniqueNamedNodes, p as uniqueStrings };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=directoryHelpers.esm.js.map
|