solid-logic 1.3.17 → 2.0.0-30dbc72f

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 (155) hide show
  1. package/.babelrc +0 -0
  2. package/.eslintrc.js +0 -0
  3. package/.github/workflows/ci.yml +0 -0
  4. package/.github/workflows/release.yml +0 -0
  5. package/.nvmrc +0 -0
  6. package/LICENSE +0 -0
  7. package/README.md +0 -0
  8. package/jest.config.js +0 -0
  9. package/lib/acl/aclLogic.d.ts +3 -30
  10. package/lib/acl/aclLogic.d.ts.map +1 -1
  11. package/lib/acl/aclLogic.js +152 -119
  12. package/lib/acl/aclLogic.js.map +1 -1
  13. package/lib/authSession/authSession.d.ts +0 -0
  14. package/lib/authSession/authSession.d.ts.map +0 -0
  15. package/lib/authSession/authSession.js +0 -0
  16. package/lib/authSession/authSession.js.map +0 -0
  17. package/lib/authn/SolidAuthnLogic.d.ts +0 -0
  18. package/lib/authn/SolidAuthnLogic.d.ts.map +1 -1
  19. package/lib/authn/SolidAuthnLogic.js +3 -3
  20. package/lib/authn/SolidAuthnLogic.js.map +1 -1
  21. package/lib/authn/authUtil.d.ts +0 -0
  22. package/lib/authn/authUtil.d.ts.map +0 -0
  23. package/lib/authn/authUtil.js +0 -0
  24. package/lib/authn/authUtil.js.map +0 -0
  25. package/lib/chat/chatLogic.d.ts +3 -0
  26. package/lib/chat/chatLogic.d.ts.map +1 -0
  27. package/lib/chat/{ChatLogic.js → chatLogic.js} +82 -86
  28. package/lib/chat/chatLogic.js.map +1 -0
  29. package/lib/inbox/inboxLogic.d.ts +3 -0
  30. package/lib/inbox/inboxLogic.d.ts.map +1 -0
  31. package/lib/inbox/{InboxLogic.js → inboxLogic.js} +58 -64
  32. package/lib/inbox/inboxLogic.js.map +1 -0
  33. package/lib/index.d.ts +6 -11
  34. package/lib/index.d.ts.map +1 -1
  35. package/lib/index.js +5 -25
  36. package/lib/index.js.map +1 -1
  37. package/lib/issuer/issuerLogic.d.ts +0 -0
  38. package/lib/issuer/issuerLogic.d.ts.map +0 -0
  39. package/lib/issuer/issuerLogic.js +1 -1
  40. package/lib/issuer/issuerLogic.js.map +1 -1
  41. package/lib/logic/CustomError.d.ts +4 -0
  42. package/lib/logic/CustomError.d.ts.map +1 -1
  43. package/lib/logic/CustomError.js +17 -1
  44. package/lib/logic/CustomError.js.map +1 -1
  45. package/lib/logic/solidLogic.d.ts +6 -0
  46. package/lib/logic/solidLogic.d.ts.map +1 -0
  47. package/lib/logic/solidLogic.js +92 -0
  48. package/lib/logic/solidLogic.js.map +1 -0
  49. package/lib/logic/solidLogicSingleton.d.ts +1 -2
  50. package/lib/logic/solidLogicSingleton.d.ts.map +1 -1
  51. package/lib/logic/solidLogicSingleton.js +3 -3
  52. package/lib/logic/solidLogicSingleton.js.map +1 -1
  53. package/lib/profile/profileLogic.d.ts +3 -0
  54. package/lib/profile/profileLogic.d.ts.map +1 -0
  55. package/lib/profile/profileLogic.js +246 -0
  56. package/lib/profile/profileLogic.js.map +1 -0
  57. package/lib/typeIndex/typeIndexLogic.d.ts +2 -21
  58. package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -1
  59. package/lib/typeIndex/typeIndexLogic.js +304 -296
  60. package/lib/typeIndex/typeIndexLogic.js.map +1 -1
  61. package/lib/types.d.ts +82 -1
  62. package/lib/types.d.ts.map +1 -1
  63. package/lib/types.js +0 -0
  64. package/lib/types.js.map +0 -0
  65. package/lib/util/containerLogic.d.ts +11 -0
  66. package/lib/util/containerLogic.d.ts.map +1 -0
  67. package/lib/{profile/ProfileLogic.js → util/containerLogic.js} +53 -44
  68. package/lib/util/containerLogic.js.map +1 -0
  69. package/lib/util/debug.d.ts +0 -0
  70. package/lib/util/debug.d.ts.map +0 -0
  71. package/lib/util/debug.js +0 -0
  72. package/lib/util/debug.js.map +0 -0
  73. package/lib/util/ns.d.ts +2 -0
  74. package/lib/util/ns.d.ts.map +1 -0
  75. package/lib/util/ns.js +34 -0
  76. package/lib/util/ns.js.map +1 -0
  77. package/lib/util/utilityLogic.d.ts +15 -0
  78. package/lib/util/utilityLogic.d.ts.map +1 -0
  79. package/lib/util/utilityLogic.js +272 -0
  80. package/lib/util/utilityLogic.js.map +1 -0
  81. package/lib/util/utils.d.ts +8 -0
  82. package/lib/util/utils.d.ts.map +1 -0
  83. package/lib/util/utils.js +48 -0
  84. package/lib/util/utils.js.map +1 -0
  85. package/package.json +17 -15
  86. package/src/acl/aclLogic.ts +137 -118
  87. package/src/authSession/authSession.ts +0 -0
  88. package/src/authn/SolidAuthnLogic.ts +8 -7
  89. package/src/authn/authUtil.ts +0 -0
  90. package/src/chat/chatLogic.ts +225 -0
  91. package/src/inbox/inboxLogic.ts +58 -0
  92. package/src/index.ts +11 -29
  93. package/src/issuer/issuerLogic.ts +1 -1
  94. package/src/logic/CustomError.ts +5 -1
  95. package/src/logic/solidLogic.ts +75 -0
  96. package/src/logic/solidLogicSingleton.ts +3 -3
  97. package/src/profile/profileLogic.ts +126 -0
  98. package/src/typeIndex/typeIndexLogic.ts +175 -182
  99. package/src/types.ts +83 -4
  100. package/src/util/containerLogic.ts +54 -0
  101. package/src/util/debug.ts +0 -0
  102. package/src/util/ns.ts +5 -0
  103. package/src/util/utilityLogic.ts +155 -0
  104. package/src/util/utils.ts +52 -0
  105. package/test/aclLogic.test.ts +13 -4
  106. package/test/authUtil.test.ts +0 -0
  107. package/test/chatLogic.test.ts +70 -71
  108. package/test/container.test.ts +56 -0
  109. package/test/helpers/dataSetup.ts +134 -0
  110. package/test/helpers/setup.ts +4 -0
  111. package/test/inboxLogic.test.ts +39 -38
  112. package/test/logic.test.ts +10 -9
  113. package/test/profileLogic.test.ts +246 -0
  114. package/test/solidAuthLogic.test.ts +0 -0
  115. package/test/typeIndexLogic.test.ts +488 -30
  116. package/test/utilityLogic.test.ts +172 -126
  117. package/test/utils.test.ts +32 -0
  118. package/tsconfig.json +0 -0
  119. package/lib/chat/ChatLogic.d.ts +0 -26
  120. package/lib/chat/ChatLogic.d.ts.map +0 -1
  121. package/lib/chat/ChatLogic.js.map +0 -1
  122. package/lib/chat/determineChatContainer.d.ts +0 -3
  123. package/lib/chat/determineChatContainer.d.ts.map +0 -1
  124. package/lib/chat/determineChatContainer.js +0 -12
  125. package/lib/chat/determineChatContainer.js.map +0 -1
  126. package/lib/discovery/discoveryLogic.d.ts +0 -13
  127. package/lib/discovery/discoveryLogic.d.ts.map +0 -1
  128. package/lib/discovery/discoveryLogic.js +0 -203
  129. package/lib/discovery/discoveryLogic.js.map +0 -1
  130. package/lib/inbox/InboxLogic.d.ts +0 -18
  131. package/lib/inbox/InboxLogic.d.ts.map +0 -1
  132. package/lib/inbox/InboxLogic.js.map +0 -1
  133. package/lib/logic/SolidLogic.d.ts +0 -48
  134. package/lib/logic/SolidLogic.d.ts.map +0 -1
  135. package/lib/logic/SolidLogic.js +0 -321
  136. package/lib/logic/SolidLogic.js.map +0 -1
  137. package/lib/profile/ProfileLogic.d.ts +0 -13
  138. package/lib/profile/ProfileLogic.d.ts.map +0 -1
  139. package/lib/profile/ProfileLogic.js.map +0 -1
  140. package/lib/util/UtilityLogic.d.ts +0 -33
  141. package/lib/util/UtilityLogic.d.ts.map +0 -1
  142. package/lib/util/UtilityLogic.js +0 -240
  143. package/lib/util/UtilityLogic.js.map +0 -1
  144. package/lib/util/uri.d.ts +0 -3
  145. package/lib/util/uri.d.ts.map +0 -1
  146. package/lib/util/uri.js +0 -9
  147. package/lib/util/uri.js.map +0 -1
  148. package/src/chat/ChatLogic.ts +0 -244
  149. package/src/chat/determineChatContainer.ts +0 -14
  150. package/src/discovery/discoveryLogic.ts +0 -90
  151. package/src/inbox/InboxLogic.ts +0 -66
  152. package/src/logic/SolidLogic.ts +0 -262
  153. package/src/profile/ProfileLogic.ts +0 -44
  154. package/src/util/UtilityLogic.ts +0 -161
  155. package/src/util/uri.ts +0 -5
@@ -1,137 +1,156 @@
1
- /**
2
- * Simple Access Control
3
- *
4
- * This function sets up a simple default ACL for a resource, with
5
- * RWC for the owner, and a specified access (default none) for the public.
6
- * In all cases owner has read write control.
7
- * Parameter lists modes allowed to public
8
- *
9
- * @param options
10
- * @param options.public eg ['Read', 'Write']
11
- *
12
- * @returns Resolves with aclDoc uri on successful write
13
- */
1
+ import { graph, NamedNode, Namespace, serialize, sym } from "rdflib"
2
+ import { AclLogic } from "../types";
3
+ import { ns as namespace } from '../util/ns'
14
4
 
15
- import { graph, NamedNode, Namespace, serialize } from "rdflib"
16
- import solidNamespace from 'solid-namespace'
17
- import * as $rdf from 'rdflib'
18
- import { solidLogicSingleton } from "../logic/solidLogicSingleton"
19
- import { ACL_LINK } from "../util/UtilityLogic"
20
5
 
21
- export const ns = solidNamespace($rdf)
6
+ export const ACL_LINK = sym(
7
+ "http://www.iana.org/assignments/link-relations/acl"
8
+ );
22
9
 
23
- export function setACLUserPublic (
24
- docURI: string,
25
- me: NamedNode,
26
- options: {
27
- defaultForNew?: boolean,
28
- public?: []
29
- }
30
- ): Promise<NamedNode> {
31
- const aclDoc = solidLogicSingleton.store.any(
32
- solidLogicSingleton.store.sym(docURI),
33
- ACL_LINK
34
- )
10
+ export function createAclLogic(store): AclLogic {
35
11
 
36
- return Promise.resolve()
37
- .then(() => {
38
- if (aclDoc) {
39
- return aclDoc as NamedNode
12
+ const ns = namespace
13
+
14
+ async function findAclDocUrl(url: string) {
15
+ const doc = store.sym(url);
16
+ await store.fetcher.load(doc);
17
+ const docNode = store.any(doc, ACL_LINK);
18
+ if (!docNode) {
19
+ throw new Error(`No ACL link discovered for ${url}`);
20
+ }
21
+ return docNode.value;
40
22
  }
41
-
42
- return fetchACLRel(docURI).catch(err => {
43
- throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)
44
- })
45
- })
46
- .then(aclDoc => {
47
- const aclText = genACLText(docURI, me, aclDoc.uri, options)
48
- if (!solidLogicSingleton.store.fetcher) {
49
- throw new Error('Cannot PUT this, store has no fetcher')
23
+ /**
24
+ * Simple Access Control
25
+ *
26
+ * This function sets up a simple default ACL for a resource, with
27
+ * RWC for the owner, and a specified access (default none) for the public.
28
+ * In all cases owner has read write control.
29
+ * Parameter lists modes allowed to public
30
+ *
31
+ * @param options
32
+ * @param options.public eg ['Read', 'Write']
33
+ *
34
+ * @returns Resolves with aclDoc uri on successful write
35
+ */
36
+ function setACLUserPublic (
37
+ docURI: string,
38
+ me: NamedNode,
39
+ options: {
40
+ defaultForNew?: boolean,
41
+ public?: []
50
42
  }
51
- return solidLogicSingleton.store.fetcher
52
- .webOperation('PUT', aclDoc.uri, {
53
- data: aclText,
54
- contentType: 'text/turtle'
55
- })
56
- .then(result => {
57
- if (!result.ok) {
58
- throw new Error('Error writing ACL text: ' + result.error)
43
+ ): Promise<NamedNode> {
44
+ const aclDoc = store.any(
45
+ store.sym(docURI),
46
+ ACL_LINK
47
+ )
48
+
49
+ return Promise.resolve()
50
+ .then(() => {
51
+ if (aclDoc) {
52
+ return aclDoc as NamedNode
59
53
  }
60
54
 
61
- return aclDoc
55
+ return fetchACLRel(docURI).catch(err => {
56
+ throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)
57
+ })
62
58
  })
63
- })
64
- }
59
+ .then(aclDoc => {
60
+ const aclText = genACLText(docURI, me, aclDoc.uri, options)
61
+ if (!store.fetcher) {
62
+ throw new Error('Cannot PUT this, store has no fetcher')
63
+ }
64
+ return store.fetcher
65
+ .webOperation('PUT', aclDoc.uri, {
66
+ data: aclText,
67
+ contentType: 'text/turtle'
68
+ })
69
+ .then(result => {
70
+ if (!result.ok) {
71
+ throw new Error('Error writing ACL text: ' + result.error)
72
+ }
65
73
 
66
- /**
67
- * @param docURI
68
- * @returns
69
- */
70
- function fetchACLRel (docURI: string): Promise<NamedNode> {
71
- const fetcher = solidLogicSingleton.store.fetcher
72
- if (!fetcher) {
73
- throw new Error('Cannot fetch ACL rel, store has no fetcher')
74
+ return aclDoc
75
+ })
76
+ })
74
77
  }
75
78
 
76
- return fetcher.load(docURI).then(result => {
77
- if (!result.ok) {
78
- throw new Error('fetchACLRel: While loading:' + (result as any).error)
79
+ /**
80
+ * @param docURI
81
+ * @returns
82
+ */
83
+ function fetchACLRel (docURI: string): Promise<NamedNode> {
84
+ const fetcher = store.fetcher
85
+ if (!fetcher) {
86
+ throw new Error('Cannot fetch ACL rel, store has no fetcher')
79
87
  }
80
88
 
81
- const aclDoc = solidLogicSingleton.store.any(
82
- solidLogicSingleton.store.sym(docURI),
83
- ACL_LINK
84
- )
89
+ return fetcher.load(docURI).then(result => {
90
+ if (!result.ok) {
91
+ throw new Error('fetchACLRel: While loading:' + (result as any).error)
92
+ }
85
93
 
86
- if (!aclDoc) {
87
- throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)
88
- }
94
+ const aclDoc = store.any(
95
+ store.sym(docURI),
96
+ ACL_LINK
97
+ )
89
98
 
90
- return aclDoc as NamedNode
91
- })
92
- }
99
+ if (!aclDoc) {
100
+ throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)
101
+ }
102
+
103
+ return aclDoc as NamedNode
104
+ })
105
+ }
93
106
 
94
- /**
95
- * @param docURI
96
- * @param me
97
- * @param aclURI
98
- * @param options
99
- *
100
- * @returns Serialized ACL
101
- */
102
- export function genACLText (
103
- docURI: string,
104
- me: NamedNode,
105
- aclURI: string,
106
- options: {
107
- defaultForNew?: boolean,
108
- public?: []
109
- } = {}
110
- ): string | undefined {
111
- const optPublic = options.public || []
112
- const g = graph()
113
- const auth = Namespace('http://www.w3.org/ns/auth/acl#')
114
- let a = g.sym(`${aclURI}#a1`)
115
- const acl = g.sym(aclURI)
116
- const doc = g.sym(docURI)
117
- g.add(a, ns.rdf('type'), auth('Authorization'), acl)
118
- g.add(a, auth('accessTo'), doc, acl)
119
- if (options.defaultForNew) {
120
- g.add(a, auth('default'), doc, acl)
121
- }
122
- g.add(a, auth('agent'), me, acl)
123
- g.add(a, auth('mode'), auth('Read'), acl)
124
- g.add(a, auth('mode'), auth('Write'), acl)
125
- g.add(a, auth('mode'), auth('Control'), acl)
107
+ /**
108
+ * @param docURI
109
+ * @param me
110
+ * @param aclURI
111
+ * @param options
112
+ *
113
+ * @returns Serialized ACL
114
+ */
115
+ function genACLText (
116
+ docURI: string,
117
+ me: NamedNode,
118
+ aclURI: string,
119
+ options: {
120
+ defaultForNew?: boolean,
121
+ public?: []
122
+ } = {}
123
+ ): string | undefined {
124
+ const optPublic = options.public || []
125
+ const g = graph()
126
+ const auth = Namespace('http://www.w3.org/ns/auth/acl#')
127
+ let a = g.sym(`${aclURI}#a1`)
128
+ const acl = g.sym(aclURI)
129
+ const doc = g.sym(docURI)
130
+ g.add(a, ns.rdf('type'), auth('Authorization'), acl)
131
+ g.add(a, auth('accessTo'), doc, acl)
132
+ if (options.defaultForNew) {
133
+ g.add(a, auth('default'), doc, acl)
134
+ }
135
+ g.add(a, auth('agent'), me, acl)
136
+ g.add(a, auth('mode'), auth('Read'), acl)
137
+ g.add(a, auth('mode'), auth('Write'), acl)
138
+ g.add(a, auth('mode'), auth('Control'), acl)
126
139
 
127
- if (optPublic.length) {
128
- a = g.sym(`${aclURI}#a2`)
129
- g.add(a, ns.rdf('type'), auth('Authorization'), acl)
130
- g.add(a, auth('accessTo'), doc, acl)
131
- g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)
132
- for (let p = 0; p < optPublic.length; p++) {
133
- g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc
140
+ if (optPublic.length) {
141
+ a = g.sym(`${aclURI}#a2`)
142
+ g.add(a, ns.rdf('type'), auth('Authorization'), acl)
143
+ g.add(a, auth('accessTo'), doc, acl)
144
+ g.add(a, auth('agentClass'), ns.foaf('Agent'), acl)
145
+ for (let p = 0; p < optPublic.length; p++) {
146
+ g.add(a, auth('mode'), auth(optPublic[p]), acl) // Like 'Read' etc
147
+ }
148
+ }
149
+ return serialize(acl, g, aclURI)
150
+ }
151
+ return {
152
+ findAclDocUrl,
153
+ setACLUserPublic,
154
+ genACLText
134
155
  }
135
- }
136
- return serialize(acl, g, aclURI)
137
- }
156
+ }
File without changes
@@ -3,22 +3,23 @@ import { appContext, offlineTestID } from "./authUtil";
3
3
  import * as debug from '../util/debug'
4
4
  import { Session } from "@inrupt/solid-client-authn-browser";
5
5
  import { AuthenticationContext, AuthnLogic } from "../types";
6
+
6
7
  export class SolidAuthnLogic implements AuthnLogic {
7
- private session: Session;
8
+ private session: Session;
8
9
 
9
10
  constructor(solidAuthSession: Session) {
10
11
  this.session = solidAuthSession;
11
12
  }
12
-
13
+
13
14
  // we created authSession getter because we want to access it as authn.authSession externally
14
- get authSession():Session { return this.session }
15
+ get authSession():Session { return this.session }
15
16
 
16
17
  currentUser(): NamedNode | null {
17
18
  const app = appContext()
18
19
  if (app.viewingNoAuthPage) {
19
20
  return sym(app.webId)
20
21
  }
21
- if (this.session.info.webId && this.session.info.isLoggedIn) {
22
+ if (this && this.session && this.session.info && this.session.info.webId && this.session.info.isLoggedIn) {
22
23
  return sym(this.session.info.webId)
23
24
  }
24
25
  return offlineTestID() // null unless testing
@@ -58,10 +59,10 @@ export class SolidAuthnLogic implements AuthnLogic {
58
59
  const curUrl = new URL(window.location.href)
59
60
  if (curUrl.hash !== postLoginRedirectHash) {
60
61
  if (history.pushState) {
61
- // console.log('Setting window.location.has using pushState')
62
+ // debug.log('Setting window.location.has using pushState')
62
63
  history.pushState(null, document.title, postLoginRedirectHash)
63
64
  } else {
64
- // console.warn('Setting window.location.has using location.hash')
65
+ // debug.warn('Setting window.location.has using location.hash')
65
66
  location.hash = postLoginRedirectHash
66
67
  }
67
68
  curUrl.hash = postLoginRedirectHash
@@ -120,4 +121,4 @@ export class SolidAuthnLogic implements AuthnLogic {
120
121
  return webId
121
122
  }
122
123
 
123
- }
124
+ }
File without changes
@@ -0,0 +1,225 @@
1
+ import { NamedNode, Node, st, term } from "rdflib"
2
+ import { ChatLogic, CreatedPaneOptions, NewPaneOptions, Chat } from "../types"
3
+ import { ns as namespace } from "../util/ns";
4
+ import { determineChatContainer, newThing } from "../util/utils"
5
+
6
+ const CHAT_LOCATION_IN_CONTAINER = "index.ttl#this"
7
+
8
+ export function createChatLogic(store, profileLogic): ChatLogic {
9
+ const ns = namespace
10
+
11
+ async function setAcl(
12
+ chatContainer: NamedNode,
13
+ me: NamedNode,
14
+ invitee: NamedNode
15
+ ): Promise<void> {
16
+ // Some servers don't present a Link http response header
17
+ // if the container doesn't exist yet, so refetch the container
18
+ // now that it has been created:
19
+ await store.fetcher.load(chatContainer);
20
+
21
+ // FIXME: check the Why value on this quad:
22
+ const chatAclDoc = store.any(
23
+ chatContainer,
24
+ new NamedNode("http://www.iana.org/assignments/link-relations/acl")
25
+ );
26
+ if (!chatAclDoc) {
27
+ throw new Error("Chat ACL doc not found!");
28
+ }
29
+
30
+ const aclBody = `
31
+ @prefix acl: <http://www.w3.org/ns/auth/acl#>.
32
+ <#owner>
33
+ a acl:Authorization;
34
+ acl:agent <${me.value}>;
35
+ acl:accessTo <.>;
36
+ acl:default <.>;
37
+ acl:mode
38
+ acl:Read, acl:Write, acl:Control.
39
+ <#invitee>
40
+ a acl:Authorization;
41
+ acl:agent <${invitee.value}>;
42
+ acl:accessTo <.>;
43
+ acl:default <.>;
44
+ acl:mode
45
+ acl:Read, acl:Append.
46
+ `;
47
+ await store.fetcher.webOperation("PUT", chatAclDoc.value, {
48
+ data: aclBody,
49
+ contentType: "text/turtle",
50
+ });
51
+ }
52
+
53
+ async function addToPrivateTypeIndex(chatThing, me) {
54
+ // Add to private type index
55
+ const privateTypeIndex = store.any(
56
+ me,
57
+ ns.solid("privateTypeIndex")
58
+ ) as NamedNode | null;
59
+ if (!privateTypeIndex) {
60
+ throw new Error("Private type index not found!");
61
+ }
62
+ await store.fetcher.load(privateTypeIndex);
63
+ const reg = newThing(privateTypeIndex);
64
+ const ins = [
65
+ st(
66
+ reg,
67
+ ns.rdf("type"),
68
+ ns.solid("TypeRegistration"),
69
+ privateTypeIndex.doc()
70
+ ),
71
+ st(
72
+ reg,
73
+ ns.solid("forClass"),
74
+ ns.meeting("LongChat"),
75
+ privateTypeIndex.doc()
76
+ ),
77
+ st(reg, ns.solid("instance"), chatThing, privateTypeIndex.doc()),
78
+ ];
79
+ await new Promise((resolve, reject) => {
80
+ store.updater.update([], ins, function (_uri, ok, errm) {
81
+ if (!ok) {
82
+ reject(new Error(errm));
83
+ } else {
84
+ resolve(null);
85
+ }
86
+ });
87
+ });
88
+ }
89
+
90
+ async function findChat(invitee: NamedNode): Promise<Chat> {
91
+ const me = await profileLogic.loadMe();
92
+ const podRoot = await profileLogic.getPodRoot(me);
93
+ const chatContainer = determineChatContainer(invitee, podRoot);
94
+ let exists = true;
95
+ try {
96
+ await store.fetcher.load(
97
+ new NamedNode(chatContainer.value + "index.ttl#this")
98
+ );
99
+ } catch (e) {
100
+ exists = false;
101
+ }
102
+ return { me, chatContainer, exists };
103
+ }
104
+
105
+ async function createChatThing(
106
+ chatContainer: NamedNode,
107
+ me: NamedNode
108
+ ): Promise<NamedNode> {
109
+ const created = await mintNew({
110
+ me,
111
+ newBase: chatContainer.value,
112
+ });
113
+ return created.newInstance;
114
+ }
115
+
116
+ function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {
117
+ const kb = store;
118
+ const updater = kb.updater;
119
+ if (newPaneOptions.me && !newPaneOptions.me.uri) {
120
+ throw new Error("chat mintNew: Invalid userid " + newPaneOptions.me);
121
+ }
122
+
123
+ const newInstance = (newPaneOptions.newInstance =
124
+ newPaneOptions.newInstance ||
125
+ kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER));
126
+ const newChatDoc = newInstance.doc();
127
+
128
+ kb.add(
129
+ newInstance,
130
+ ns.rdf("type"),
131
+ ns.meeting("LongChat"),
132
+ newChatDoc
133
+ );
134
+ kb.add(newInstance, ns.dc("title"), "Chat channel", newChatDoc);
135
+ kb.add(
136
+ newInstance,
137
+ ns.dc("created"),
138
+ term<Node>(new Date(Date.now())),
139
+ newChatDoc
140
+ );
141
+ if (newPaneOptions.me) {
142
+ kb.add(newInstance, ns.dc("author"), newPaneOptions.me, newChatDoc);
143
+ }
144
+
145
+ return new Promise(function (resolve, reject) {
146
+ updater?.put(
147
+ newChatDoc,
148
+ kb.statementsMatching(undefined, undefined, undefined, newChatDoc),
149
+ "text/turtle",
150
+ function (uri2, ok, message) {
151
+ if (ok) {
152
+ resolve({
153
+ ...newPaneOptions,
154
+ newInstance,
155
+ });
156
+ } else {
157
+ reject(
158
+ new Error(
159
+ "FAILED to save new chat channel at: " + uri2 + " : " + message
160
+ )
161
+ );
162
+ }
163
+ }
164
+ );
165
+ });
166
+ }
167
+
168
+ /**
169
+ * Find (and optionally create) an individual chat between the current user and the given invitee
170
+ * @param invitee - The person to chat with
171
+ * @param createIfMissing - Whether the chat should be created, if missing
172
+ * @returns null if missing, or a node referring to an already existing chat, or the newly created chat
173
+ */
174
+ async function getChat(
175
+ invitee: NamedNode,
176
+ createIfMissing = true
177
+ ): Promise<NamedNode | null> {
178
+ const { me, chatContainer, exists } = await findChat(invitee);
179
+ if (exists) {
180
+ return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER);
181
+ }
182
+
183
+ if (createIfMissing) {
184
+ const chatThing = await createChatThing(chatContainer, me);
185
+ await sendInvite(invitee, chatThing);
186
+ await setAcl(chatContainer, me, invitee);
187
+ await addToPrivateTypeIndex(chatThing, me);
188
+ return chatThing;
189
+ }
190
+ return null;
191
+ }
192
+
193
+ async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {
194
+ await store.fetcher.load(invitee.doc());
195
+ const inviteeInbox = store.any(
196
+ invitee,
197
+ ns.ldp("inbox"),
198
+ undefined,
199
+ invitee.doc()
200
+ );
201
+ if (!inviteeInbox) {
202
+ throw new Error(`Invitee inbox not found! ${invitee.value}`);
203
+ }
204
+ const inviteBody = `
205
+ <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;
206
+ ${ns.rdf("seeAlso")} <${chatThing.value}> .
207
+ `;
208
+
209
+ const inviteResponse = await store.fetcher?.webOperation(
210
+ "POST",
211
+ inviteeInbox.value,
212
+ {
213
+ data: inviteBody,
214
+ contentType: "text/turtle",
215
+ }
216
+ );
217
+ const locationStr = inviteResponse?.headers.get("location");
218
+ if (!locationStr) {
219
+ throw new Error(`Invite sending returned a ${inviteResponse?.status}`);
220
+ }
221
+ }
222
+ return {
223
+ setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew
224
+ }
225
+ }
@@ -0,0 +1,58 @@
1
+ import { NamedNode } from "rdflib";
2
+ import { InboxLogic } from "../types";
3
+ import { getArchiveUrl } from "../util/utils";
4
+
5
+ export function createInboxLogic(store, profileLogic, utilityLogic, containerLogic, aclLogic): InboxLogic {
6
+
7
+ async function createInboxFor(peerWebId: string, nick: string) {
8
+ const myWebId: NamedNode = await profileLogic.loadMe();
9
+ const podRoot: NamedNode = await profileLogic.getPodRoot(myWebId);
10
+ const ourInbox = `${podRoot.value}p2p-inboxes/${encodeURIComponent(nick)}/`;
11
+ await containerLogic.createContainer(ourInbox);
12
+ const aclDocUrl = await aclLogic.findAclDocUrl(ourInbox);
13
+ await utilityLogic.setSinglePeerAccess({
14
+ ownerWebId: myWebId.value,
15
+ peerWebId,
16
+ accessToModes: 'acl:Append',
17
+ target: ourInbox
18
+ });
19
+ return ourInbox;
20
+ }
21
+
22
+ async function getNewMessages(
23
+ user?: NamedNode
24
+ ): Promise<string[]> {
25
+ if (!user) {
26
+ user = await profileLogic.loadMe();
27
+ }
28
+ const inbox = await profileLogic.getMainInbox(user);
29
+ const urls = await containerLogic.getContainerMembers(inbox.value);
30
+ return urls.filter(url => !containerLogic.isContainer(url));
31
+ }
32
+
33
+ async function markAsRead(url: string, date: Date) {
34
+ const downloaded = await store.fetcher._fetch(url);
35
+ if (downloaded.status !== 200) {
36
+ throw new Error(`Not OK! ${url}`);
37
+ }
38
+ const archiveUrl = getArchiveUrl(url, date);
39
+ const options = {
40
+ method: 'PUT',
41
+ body: await downloaded.text(),
42
+ headers: [
43
+ ['Content-Type', downloaded.headers.get('Content-Type') || 'application/octet-stream']
44
+ ]
45
+ };
46
+ const uploaded = await store.fetcher._fetch(archiveUrl, options);
47
+ if (uploaded.status.toString()[0] === '2') {
48
+ await store.fetcher._fetch(url, {
49
+ method: 'DELETE'
50
+ });
51
+ }
52
+ }
53
+ return {
54
+ createInboxFor,
55
+ getNewMessages,
56
+ markAsRead
57
+ }
58
+ }
package/src/index.ts CHANGED
@@ -1,39 +1,21 @@
1
1
  // Make these variables directly accessible as it is what you need most of the time
2
2
  // This also makes these variable globaly accesible in mashlib
3
3
  import { solidLogicSingleton } from './logic/solidLogicSingleton'
4
+
4
5
  const authn = solidLogicSingleton.authn
5
6
  const authSession = solidLogicSingleton.authn.authSession
6
7
  const store = solidLogicSingleton.store
7
8
 
8
- const chat = solidLogicSingleton.chat
9
- const profile = solidLogicSingleton.profile
10
-
11
- export {
12
- setACLUserPublic,
13
- genACLText
14
- } from './acl/aclLogic'
15
-
16
- export {
17
- ensureTypeIndexes,
18
- loadTypeIndexes,
19
- registerInTypeIndex,
20
- loadIndex
21
- } from './typeIndex/typeIndexLogic'
9
+ export { ACL_LINK } from './acl/aclLogic'
10
+ export { offlineTestID, appContext } from './authn/authUtil'
11
+ export { getSuggestedIssuers } from './issuer/issuerLogic'
12
+ export { AppDetails, SolidNamespace, AuthenticationContext, SolidLogic } from './types'
13
+ export { UnauthorizedError, CrossOriginForbiddenError, SameOriginForbiddenError, NotFoundError, FetchError, NotEditableError, WebOperationError } from './logic/CustomError'
22
14
 
23
15
  export {
24
- loadProfile,
25
- loadPreferences,
26
- loadTypeIndexesFor,
27
- loadCommunityTypeIndexes,
28
- loadAllTypeIndexes
29
- } from './discovery/discoveryLogic'
16
+ solidLogicSingleton, // solidLogicSingleton is exported entirely because it is used in solid-panes
17
+ store,
18
+ authn,
19
+ authSession
20
+ }
30
21
 
31
- export { SolidLogic } from './logic/SolidLogic'
32
- export { offlineTestID, appContext } from './authn/authUtil'
33
- export { ACL_LINK } from './util/UtilityLogic'
34
- export { getSuggestedIssuers } from './issuer/issuerLogic'
35
- export { AppDetails, SolidNamespace, AuthenticationContext } from './types'
36
- // solidLogicSingleton is exported entirely because it is used in solid-panes
37
- export { solidLogicSingleton } from './logic/solidLogicSingleton'
38
- export { UnauthorizedError, CrossOriginForbiddenError, SameOriginForbiddenError, NotFoundError, FetchError } from './logic/CustomError'
39
- export { authn, authSession, store, chat, profile }
@@ -13,7 +13,7 @@ const DEFAULT_ISSUERS = [
13
13
  },
14
14
  {
15
15
  name: 'pod.Inrupt.com',
16
- uri: 'https://broker.pod.inrupt.com'
16
+ uri: 'https://login.inrupt.com'
17
17
  }
18
18
  ]
19
19