solid-logic 3.0.9-f51524a8 → 3.0.9-ff53d0a

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 (127) hide show
  1. package/README.md +103 -2
  2. package/dist/acl/aclLogic.js +118 -0
  3. package/dist/acl/aclLogic.js.map +1 -0
  4. package/{lib → dist}/authSession/authSession.d.ts.map +1 -1
  5. package/dist/authSession/authSession.js +3 -0
  6. package/dist/authSession/authSession.js.map +1 -0
  7. package/{lib → dist}/authn/SolidAuthnLogic.d.ts.map +1 -1
  8. package/dist/authn/SolidAuthnLogic.js +110 -0
  9. package/dist/authn/SolidAuthnLogic.js.map +1 -0
  10. package/dist/authn/authUtil.js +67 -0
  11. package/dist/authn/authUtil.js.map +1 -0
  12. package/dist/chat/chatLogic.js +157 -0
  13. package/dist/chat/chatLogic.js.map +1 -0
  14. package/dist/inbox/inboxLogic.js +52 -0
  15. package/dist/inbox/inboxLogic.js.map +1 -0
  16. package/dist/index.js +13 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/issuer/issuerLogic.js +37 -0
  19. package/dist/issuer/issuerLogic.js.map +1 -0
  20. package/dist/logic/CustomError.js +28 -0
  21. package/dist/logic/CustomError.js.map +1 -0
  22. package/dist/logic/solidLogic.js +65 -0
  23. package/dist/logic/solidLogic.js.map +1 -0
  24. package/dist/logic/solidLogicSingleton.js +18 -0
  25. package/dist/logic/solidLogicSingleton.js.map +1 -0
  26. package/dist/profile/profileLogic.js +129 -0
  27. package/dist/profile/profileLogic.js.map +1 -0
  28. package/dist/solid-logic.esm.js +8560 -0
  29. package/dist/solid-logic.esm.js.map +1 -0
  30. package/dist/solid-logic.esm.min.js +32 -0
  31. package/dist/solid-logic.esm.min.js.map +1 -0
  32. package/dist/solid-logic.umd.js +8597 -0
  33. package/dist/solid-logic.umd.js.map +1 -0
  34. package/dist/solid-logic.umd.min.js +32 -0
  35. package/dist/solid-logic.umd.min.js.map +1 -0
  36. package/dist/typeIndex/typeIndexLogic.js +186 -0
  37. package/dist/typeIndex/typeIndexLogic.js.map +1 -0
  38. package/dist/types.js +2 -0
  39. package/dist/types.js.map +1 -0
  40. package/{src/util/containerLogic.ts → dist/util/containerLogic.js} +18 -26
  41. package/dist/util/containerLogic.js.map +1 -0
  42. package/dist/util/debug.js +14 -0
  43. package/dist/util/debug.js.map +1 -0
  44. package/dist/util/ns.js +5 -0
  45. package/dist/util/ns.js.map +1 -0
  46. package/dist/util/utilityLogic.js +144 -0
  47. package/dist/util/utilityLogic.js.map +1 -0
  48. package/dist/util/utils.js +39 -0
  49. package/dist/util/utils.js.map +1 -0
  50. package/package.json +28 -9
  51. package/babel.config.js +0 -6
  52. package/eslint.config.js +0 -28
  53. package/jest.config.js +0 -17
  54. package/lib/solid-logic.js +0 -107
  55. package/lib/solid-logic.js.map +0 -1
  56. package/rollup.config.js +0 -29
  57. package/src/acl/aclLogic.ts +0 -156
  58. package/src/authSession/authSession.ts +0 -13
  59. package/src/authn/SolidAuthnLogic.ts +0 -126
  60. package/src/authn/authUtil.ts +0 -70
  61. package/src/chat/chatLogic.ts +0 -226
  62. package/src/inbox/inboxLogic.ts +0 -59
  63. package/src/index.ts +0 -21
  64. package/src/issuer/issuerLogic.ts +0 -40
  65. package/src/logic/CustomError.ts +0 -29
  66. package/src/logic/solidLogic.ts +0 -76
  67. package/src/logic/solidLogicSingleton.ts +0 -20
  68. package/src/profile/profileLogic.ts +0 -125
  69. package/src/typeIndex/typeIndexLogic.ts +0 -198
  70. package/src/types.ts +0 -122
  71. package/src/util/debug.ts +0 -16
  72. package/src/util/ns.ts +0 -5
  73. package/src/util/utilityLogic.ts +0 -156
  74. package/src/util/utils.ts +0 -52
  75. package/src/versionInfo.ts +0 -32
  76. package/test/aclLogic.test.ts +0 -24
  77. package/test/authUtil.test.ts +0 -23
  78. package/test/chatLogic.test.ts +0 -322
  79. package/test/container.test.ts +0 -58
  80. package/test/helpers/dataSetup.ts +0 -135
  81. package/test/helpers/setup.ts +0 -22
  82. package/test/inboxLogic.test.ts +0 -209
  83. package/test/logic.test.ts +0 -29
  84. package/test/profileLogic.test.ts +0 -248
  85. package/test/solidAuthLogic.test.ts +0 -49
  86. package/test/typeIndexLogic.test.ts +0 -255
  87. package/test/utilityLogic.test.ts +0 -180
  88. package/test/utils.test.ts +0 -32
  89. package/timestamp.sh +0 -13
  90. package/tsconfig.json +0 -77
  91. package/tsconfig.test.json +0 -8
  92. /package/{lib → dist}/acl/aclLogic.d.ts +0 -0
  93. /package/{lib → dist}/acl/aclLogic.d.ts.map +0 -0
  94. /package/{lib → dist}/authSession/authSession.d.ts +0 -0
  95. /package/{lib → dist}/authn/SolidAuthnLogic.d.ts +0 -0
  96. /package/{lib → dist}/authn/authUtil.d.ts +0 -0
  97. /package/{lib → dist}/authn/authUtil.d.ts.map +0 -0
  98. /package/{lib → dist}/chat/chatLogic.d.ts +0 -0
  99. /package/{lib → dist}/chat/chatLogic.d.ts.map +0 -0
  100. /package/{lib → dist}/inbox/inboxLogic.d.ts +0 -0
  101. /package/{lib → dist}/inbox/inboxLogic.d.ts.map +0 -0
  102. /package/{lib → dist}/index.d.ts +0 -0
  103. /package/{lib → dist}/index.d.ts.map +0 -0
  104. /package/{lib → dist}/issuer/issuerLogic.d.ts +0 -0
  105. /package/{lib → dist}/issuer/issuerLogic.d.ts.map +0 -0
  106. /package/{lib → dist}/logic/CustomError.d.ts +0 -0
  107. /package/{lib → dist}/logic/CustomError.d.ts.map +0 -0
  108. /package/{lib → dist}/logic/solidLogic.d.ts +0 -0
  109. /package/{lib → dist}/logic/solidLogic.d.ts.map +0 -0
  110. /package/{lib → dist}/logic/solidLogicSingleton.d.ts +0 -0
  111. /package/{lib → dist}/logic/solidLogicSingleton.d.ts.map +0 -0
  112. /package/{lib → dist}/profile/profileLogic.d.ts +0 -0
  113. /package/{lib → dist}/profile/profileLogic.d.ts.map +0 -0
  114. /package/{lib → dist}/typeIndex/typeIndexLogic.d.ts +0 -0
  115. /package/{lib → dist}/typeIndex/typeIndexLogic.d.ts.map +0 -0
  116. /package/{lib → dist}/types.d.ts +0 -0
  117. /package/{lib → dist}/types.d.ts.map +0 -0
  118. /package/{lib → dist}/util/containerLogic.d.ts +0 -0
  119. /package/{lib → dist}/util/containerLogic.d.ts.map +0 -0
  120. /package/{lib → dist}/util/debug.d.ts +0 -0
  121. /package/{lib → dist}/util/debug.d.ts.map +0 -0
  122. /package/{lib → dist}/util/ns.d.ts +0 -0
  123. /package/{lib → dist}/util/ns.d.ts.map +0 -0
  124. /package/{lib → dist}/util/utilityLogic.d.ts +0 -0
  125. /package/{lib → dist}/util/utilityLogic.d.ts.map +0 -0
  126. /package/{lib → dist}/util/utils.d.ts +0 -0
  127. /package/{lib → dist}/util/utils.d.ts.map +0 -0
package/rollup.config.js DELETED
@@ -1,29 +0,0 @@
1
- import resolve from '@rollup/plugin-node-resolve'
2
- import commonjs from '@rollup/plugin-commonjs'
3
- import typescript from '@rollup/plugin-typescript'
4
- import { terser } from 'rollup-plugin-terser'
5
- import fs from 'fs'
6
- import json from '@rollup/plugin-json'
7
-
8
- const license = fs.readFileSync('./LICENSE', 'utf8')
9
-
10
- export default {
11
- input: 'src/index.ts',
12
- output: {
13
- file: 'lib/solid-logic.js',
14
- format: 'esm',
15
- banner: `/*!\n${license}\n*/`,
16
- sourcemap: true
17
- },
18
- plugins: [
19
- resolve({ preferBuiltins: true }), // best practice to be true, chooses node.js buildins
20
- commonjs(),
21
- typescript({
22
- declaration: false, // this is false so it does not generate types for the versionInfo file
23
- declarationMap: false
24
- }),
25
- json(),
26
- terser()
27
- ],
28
- inlineDynamicImports: true // dissables multiple chunk creation, why we use rollup in the first place
29
- }
@@ -1,156 +0,0 @@
1
- import { graph, NamedNode, Namespace, serialize, sym } from 'rdflib'
2
- import { AclLogic } from '../types'
3
- import { ns as namespace } from '../util/ns'
4
-
5
-
6
- export const ACL_LINK = sym(
7
- 'http://www.iana.org/assignments/link-relations/acl'
8
- )
9
-
10
- export function createAclLogic(store): AclLogic {
11
-
12
- const ns = namespace
13
-
14
- async function findAclDocUrl(url: NamedNode) {
15
- await store.fetcher.load(url)
16
- const docNode = store.any(url, ACL_LINK)
17
- if (!docNode) {
18
- throw new Error(`No ACL link discovered for ${url}`)
19
- }
20
- return docNode.value
21
- }
22
- /**
23
- * Simple Access Control
24
- *
25
- * This function sets up a simple default ACL for a resource, with
26
- * RWC for the owner, and a specified access (default none) for the public.
27
- * In all cases owner has read write control.
28
- * Parameter lists modes allowed to public
29
- *
30
- * @param options
31
- * @param options.public eg ['Read', 'Write']
32
- *
33
- * @returns Resolves with aclDoc uri on successful write
34
- */
35
- function setACLUserPublic (
36
- docURI: string,
37
- me: NamedNode,
38
- options: {
39
- defaultForNew?: boolean,
40
- public?: []
41
- }
42
- ): Promise<NamedNode> {
43
- const aclDoc = store.any(
44
- store.sym(docURI),
45
- ACL_LINK
46
- )
47
-
48
- return Promise.resolve()
49
- .then(() => {
50
- if (aclDoc) {
51
- return aclDoc as NamedNode
52
- }
53
-
54
- return fetchACLRel(docURI).catch(err => {
55
- throw new Error(`Error fetching rel=ACL header for ${docURI}: ${err}`)
56
- })
57
- })
58
- .then(aclDoc => {
59
- const aclText = genACLText(docURI, me, aclDoc.uri, options)
60
- if (!store.fetcher) {
61
- throw new Error('Cannot PUT this, store has no fetcher')
62
- }
63
- return store.fetcher
64
- .webOperation('PUT', aclDoc.uri, {
65
- data: aclText,
66
- contentType: 'text/turtle'
67
- })
68
- .then(result => {
69
- if (!result.ok) {
70
- throw new Error('Error writing ACL text: ' + result.error)
71
- }
72
-
73
- return aclDoc
74
- })
75
- })
76
- }
77
-
78
- /**
79
- * @param docURI
80
- * @returns
81
- */
82
- function fetchACLRel (docURI: string): Promise<NamedNode> {
83
- const fetcher = store.fetcher
84
- if (!fetcher) {
85
- throw new Error('Cannot fetch ACL rel, store has no fetcher')
86
- }
87
-
88
- return fetcher.load(docURI).then(result => {
89
- if (!result.ok) {
90
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
91
- throw new Error('fetchACLRel: While loading:' + (result as any).error)
92
- }
93
-
94
- const aclDoc = store.any(
95
- store.sym(docURI),
96
- ACL_LINK
97
- )
98
-
99
- if (!aclDoc) {
100
- throw new Error('fetchACLRel: No Link rel=ACL header for ' + docURI)
101
- }
102
-
103
- return aclDoc as NamedNode
104
- })
105
- }
106
-
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)
139
-
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
155
- }
156
- }
@@ -1,13 +0,0 @@
1
- import {
2
- Session,
3
- getClientAuthenticationWithDependencies
4
- } from '@inrupt/solid-client-authn-browser'
5
-
6
- export const authSession = new Session(
7
- {
8
- clientAuthentication: getClientAuthenticationWithDependencies({})
9
- },
10
- 'mySession'
11
- )
12
-
13
-
@@ -1,126 +0,0 @@
1
- import { namedNode, NamedNode, sym } from 'rdflib'
2
- import { appContext, offlineTestID } from './authUtil'
3
- import * as debug from '../util/debug'
4
- import { Session } from '@inrupt/solid-client-authn-browser'
5
- import { AuthenticationContext, AuthnLogic } from '../types'
6
-
7
- export class SolidAuthnLogic implements AuthnLogic {
8
- private session: Session
9
-
10
- constructor(solidAuthSession: Session) {
11
- this.session = solidAuthSession
12
- }
13
-
14
- // we created authSession getter because we want to access it as authn.authSession externally
15
- get authSession():Session { return this.session }
16
-
17
- currentUser(): NamedNode | null {
18
- const app = appContext()
19
- if (app.viewingNoAuthPage) {
20
- return sym(app.webId)
21
- }
22
- if (this && this.session && this.session.info && this.session.info.webId && this.session.info.isLoggedIn) {
23
- return sym(this.session.info.webId)
24
- }
25
- return offlineTestID() // null unless testing
26
- }
27
-
28
- /**
29
- * Retrieves currently logged in webId from either
30
- * defaultTestUser or SolidAuth
31
- * Also activates a session after login
32
- * @param [setUserCallback] Optional callback
33
- * @returns Resolves with webId uri, if no callback provided
34
- */
35
- async checkUser<T> (
36
- setUserCallback?: (me: NamedNode | null) => T
37
- ): Promise<NamedNode | T | null> {
38
- // Save hash for "restorePreviousSession"
39
- const preLoginRedirectHash = new URL(window.location.href).hash
40
- if (preLoginRedirectHash) {
41
- window.localStorage.setItem('preLoginRedirectHash', preLoginRedirectHash)
42
- }
43
- this.session.onSessionRestore((url) => {
44
- if (document.location.toString() !== url) history.replaceState(null, '', url)
45
- })
46
-
47
- /**
48
- * Handle a successful authentication redirect
49
- */
50
- const redirectUrl = new URL(window.location.href)
51
- redirectUrl.hash = ''
52
- await this.session
53
- .handleIncomingRedirect({
54
- restorePreviousSession: true,
55
- url: redirectUrl.href
56
- })
57
-
58
- // Check to see if a hash was stored in local storage
59
- const postLoginRedirectHash = window.localStorage.getItem('preLoginRedirectHash')
60
- if (postLoginRedirectHash) {
61
- const curUrl = new URL(window.location.href)
62
- if (curUrl.hash !== postLoginRedirectHash) {
63
- if (history.pushState) {
64
- // debug.log('Setting window.location.has using pushState')
65
- history.pushState(null, document.title, postLoginRedirectHash)
66
- } else {
67
- // debug.warn('Setting window.location.has using location.hash')
68
- location.hash = postLoginRedirectHash
69
- }
70
- curUrl.hash = postLoginRedirectHash
71
- }
72
- // See https://stackoverflow.com/questions/3870057/how-can-i-update-window-location-hash-without-jumping-the-document
73
- // window.location.href = curUrl.toString()// @@ See https://developer.mozilla.org/en-US/docs/Web/API/Window/location
74
- window.localStorage.setItem('preLoginRedirectHash', '')
75
- }
76
-
77
- // Check to see if already logged in / have the WebID
78
- let me = offlineTestID()
79
- if (me) {
80
- return Promise.resolve(setUserCallback ? setUserCallback(me) : me)
81
- }
82
-
83
- const webId = this.webIdFromSession(this.session.info)
84
- if (webId) {
85
- me = this.saveUser(webId)
86
- }
87
-
88
- if (me) {
89
- debug.log(`(Logged in as ${me} by authentication)`)
90
- }
91
-
92
- return Promise.resolve(setUserCallback ? setUserCallback(me) : me)
93
- }
94
-
95
- /**
96
- * Saves `webId` in `context.me`
97
- * @param webId
98
- * @param context
99
- *
100
- * @returns Returns the WebID, after setting it
101
- */
102
- saveUser (
103
- webId: NamedNode | string | null,
104
- context?: AuthenticationContext
105
- ): NamedNode | null {
106
- let webIdUri: string
107
- if (webId) {
108
- webIdUri = (typeof webId === 'string') ? webId : webId.uri
109
- const me = namedNode(webIdUri)
110
- if (context) {
111
- context.me = me
112
- }
113
- return me
114
- }
115
- return null
116
- }
117
-
118
- /**
119
- * @returns {Promise<string|null>} Resolves with WebID URI or null
120
- */
121
- webIdFromSession (session?: { webId?: string, isLoggedIn: boolean }): string | null {
122
- const webId = session?.webId && session.isLoggedIn ? session.webId : null
123
- return webId
124
- }
125
-
126
- }
@@ -1,70 +0,0 @@
1
- import { NamedNode, sym } from 'rdflib'
2
- import * as debug from '../util/debug'
3
-
4
- /**
5
- * find a user or app's context as set in window.SolidAppContext
6
- * this is a const, not a function, because we have problems to jest mock it otherwise
7
- * see: https://github.com/facebook/jest/issues/936#issuecomment-545080082 for more
8
- * @return {any} - an appContext object
9
- */
10
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
- export const appContext = ():any => {
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- let { SolidAppContext }: any = window
14
- SolidAppContext ||= {}
15
- SolidAppContext.viewingNoAuthPage = false
16
- if (SolidAppContext.noAuth && window.document) {
17
- const currentPage = window.document.location.href
18
- if (currentPage.startsWith(SolidAppContext.noAuth)) {
19
- SolidAppContext.viewingNoAuthPage = true
20
- const params = new URLSearchParams(window.document.location.search)
21
- if (params) {
22
- let viewedPage = SolidAppContext.viewedPage = params.get('uri') || null
23
- if (viewedPage) {
24
- viewedPage = decodeURI(viewedPage)
25
- if (!viewedPage.startsWith(SolidAppContext.noAuth)) {
26
- const ary = viewedPage.split(/\//)
27
- SolidAppContext.idp = ary[0] + '//' + ary[2]
28
- SolidAppContext.viewingNoAuthPage = false
29
- }
30
- }
31
- }
32
- }
33
- }
34
- return SolidAppContext
35
- }
36
-
37
- /**
38
- * Returns `sym($SolidTestEnvironment.username)` if
39
- * `$SolidTestEnvironment.username` is defined as a global
40
- * or
41
- * returns testID defined in the HTML page
42
- * @returns {NamedNode|null}
43
- */
44
- export function offlineTestID (): NamedNode | null {
45
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
- const { $SolidTestEnvironment }: any = window
47
- if (
48
- typeof $SolidTestEnvironment !== 'undefined' &&
49
- $SolidTestEnvironment.username
50
- ) {
51
- // Test setup
52
- debug.log('Assuming the user is ' + $SolidTestEnvironment.username)
53
- return sym($SolidTestEnvironment.username)
54
- }
55
- // hack that makes SolidOS work in offline mode by adding the webId directly in html
56
- // example usage: https://github.com/solidos/mashlib/blob/29b8b53c46bf02e0e219f0bacd51b0e9951001dd/test/contact/local.html#L37
57
- if (
58
- typeof document !== 'undefined' &&
59
- document.location &&
60
- ('' + document.location).slice(0, 16) === 'http://localhost'
61
- ) {
62
- const div = document.getElementById('appTarget')
63
- if (!div) return null
64
- const id = div.getAttribute('testID')
65
- if (!id) return null
66
- debug.log('Assuming user is ' + id)
67
- return sym(id)
68
- }
69
- return null
70
- }
@@ -1,226 +0,0 @@
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
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
100
- } catch (e) {
101
- exists = false
102
- }
103
- return { me, chatContainer, exists }
104
- }
105
-
106
- async function createChatThing(
107
- chatContainer: NamedNode,
108
- me: NamedNode
109
- ): Promise<NamedNode> {
110
- const created = await mintNew({
111
- me,
112
- newBase: chatContainer.value,
113
- })
114
- return created.newInstance
115
- }
116
-
117
- function mintNew(newPaneOptions: NewPaneOptions): Promise<CreatedPaneOptions> {
118
- const kb = store
119
- const updater = kb.updater
120
- if (newPaneOptions.me && !newPaneOptions.me.uri) {
121
- throw new Error('chat mintNew: Invalid userid ' + newPaneOptions.me)
122
- }
123
-
124
- const newInstance = (newPaneOptions.newInstance =
125
- newPaneOptions.newInstance ||
126
- kb.sym(newPaneOptions.newBase + CHAT_LOCATION_IN_CONTAINER))
127
- const newChatDoc = newInstance.doc()
128
-
129
- kb.add(
130
- newInstance,
131
- ns.rdf('type'),
132
- ns.meeting('LongChat'),
133
- newChatDoc
134
- )
135
- kb.add(newInstance, ns.dc('title'), 'Chat channel', newChatDoc)
136
- kb.add(
137
- newInstance,
138
- ns.dc('created'),
139
- term<Node>(new Date(Date.now())),
140
- newChatDoc
141
- )
142
- if (newPaneOptions.me) {
143
- kb.add(newInstance, ns.dc('author'), newPaneOptions.me, newChatDoc)
144
- }
145
-
146
- return new Promise(function (resolve, reject) {
147
- updater?.put(
148
- newChatDoc,
149
- kb.statementsMatching(undefined, undefined, undefined, newChatDoc),
150
- 'text/turtle',
151
- function (uri2, ok, message) {
152
- if (ok) {
153
- resolve({
154
- ...newPaneOptions,
155
- newInstance,
156
- })
157
- } else {
158
- reject(
159
- new Error(
160
- 'FAILED to save new chat channel at: ' + uri2 + ' : ' + message
161
- )
162
- )
163
- }
164
- }
165
- )
166
- })
167
- }
168
-
169
- /**
170
- * Find (and optionally create) an individual chat between the current user and the given invitee
171
- * @param invitee - The person to chat with
172
- * @param createIfMissing - Whether the chat should be created, if missing
173
- * @returns null if missing, or a node referring to an already existing chat, or the newly created chat
174
- */
175
- async function getChat(
176
- invitee: NamedNode,
177
- createIfMissing = true
178
- ): Promise<NamedNode | null> {
179
- const { me, chatContainer, exists } = await findChat(invitee)
180
- if (exists) {
181
- return new NamedNode(chatContainer.value + CHAT_LOCATION_IN_CONTAINER)
182
- }
183
-
184
- if (createIfMissing) {
185
- const chatThing = await createChatThing(chatContainer, me)
186
- await sendInvite(invitee, chatThing)
187
- await setAcl(chatContainer, me, invitee)
188
- await addToPrivateTypeIndex(chatThing, me)
189
- return chatThing
190
- }
191
- return null
192
- }
193
-
194
- async function sendInvite(invitee: NamedNode, chatThing: NamedNode) {
195
- await store.fetcher.load(invitee.doc())
196
- const inviteeInbox = store.any(
197
- invitee,
198
- ns.ldp('inbox'),
199
- undefined,
200
- invitee.doc()
201
- )
202
- if (!inviteeInbox) {
203
- throw new Error(`Invitee inbox not found! ${invitee.value}`)
204
- }
205
- const inviteBody = `
206
- <> a <http://www.w3.org/ns/pim/meeting#LongChatInvite> ;
207
- ${ns.rdf('seeAlso')} <${chatThing.value}> .
208
- `
209
-
210
- const inviteResponse = await store.fetcher?.webOperation(
211
- 'POST',
212
- inviteeInbox.value,
213
- {
214
- data: inviteBody,
215
- contentType: 'text/turtle',
216
- }
217
- )
218
- const locationStr = inviteResponse?.headers.get('location')
219
- if (!locationStr) {
220
- throw new Error(`Invite sending returned a ${inviteResponse?.status}`)
221
- }
222
- }
223
- return {
224
- setAcl, addToPrivateTypeIndex, findChat, createChatThing, getChat, sendInvite, mintNew
225
- }
226
- }
@@ -1,59 +0,0 @@
1
- import { NamedNode } from 'rdflib'
2
- import { InboxLogic } from '../types'
3
- import { getArchiveUrl } from '../util/utils'
4
-
5
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
- export function createInboxLogic(store, profileLogic, utilityLogic, containerLogic, aclLogic): InboxLogic {
7
-
8
- async function createInboxFor(peerWebId: string, nick: string) {
9
- const myWebId: NamedNode = await profileLogic.loadMe()
10
- const podRoot: NamedNode = await profileLogic.getPodRoot(myWebId)
11
- const ourInbox = `${podRoot.value}p2p-inboxes/${encodeURIComponent(nick)}/`
12
- await containerLogic.createContainer(ourInbox)
13
- // const aclDocUrl = await aclLogic.findAclDocUrl(ourInbox);
14
- await utilityLogic.setSinglePeerAccess({
15
- ownerWebId: myWebId.value,
16
- peerWebId,
17
- accessToModes: 'acl:Append',
18
- target: ourInbox
19
- })
20
- return ourInbox
21
- }
22
-
23
- async function getNewMessages(
24
- user?: NamedNode
25
- ): Promise<NamedNode[]> {
26
- if (!user) {
27
- user = await profileLogic.loadMe()
28
- }
29
- const inbox = await profileLogic.getMainInbox(user)
30
- const urls = await containerLogic.getContainerMembers(inbox)
31
- return urls.filter(url => !containerLogic.isContainer(url))
32
- }
33
-
34
- async function markAsRead(url: string, date: Date) {
35
- const downloaded = await store.fetcher._fetch(url)
36
- if (downloaded.status !== 200) {
37
- throw new Error(`Not OK! ${url}`)
38
- }
39
- const archiveUrl = getArchiveUrl(url, date)
40
- const options = {
41
- method: 'PUT',
42
- body: await downloaded.text(),
43
- headers: [
44
- ['Content-Type', downloaded.headers.get('Content-Type') || 'application/octet-stream']
45
- ]
46
- }
47
- const uploaded = await store.fetcher._fetch(archiveUrl, options)
48
- if (uploaded.status.toString()[0] === '2') {
49
- await store.fetcher._fetch(url, {
50
- method: 'DELETE'
51
- })
52
- }
53
- }
54
- return {
55
- createInboxFor,
56
- getNewMessages,
57
- markAsRead
58
- }
59
- }