solid-logic 1.3.17-615b75c1 → 1.3.17-80b4d030
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/jest.config.js +1 -1
- package/lib/acl/aclLogic.d.ts +12 -30
- package/lib/acl/aclLogic.d.ts.map +1 -1
- package/lib/acl/aclLogic.js +152 -119
- package/lib/acl/aclLogic.js.map +1 -1
- package/lib/authn/SolidAuthnLogic.d.ts.map +1 -1
- package/lib/authn/SolidAuthnLogic.js +2 -2
- package/lib/authn/SolidAuthnLogic.js.map +1 -1
- package/lib/chat/chatLogic.d.ts +16 -0
- package/lib/chat/chatLogic.d.ts.map +1 -0
- package/lib/chat/{ChatLogic.js → chatLogic.js} +82 -87
- package/lib/chat/chatLogic.js.map +1 -0
- package/lib/inbox/inboxLogic.d.ts +7 -0
- package/lib/inbox/inboxLogic.d.ts.map +1 -0
- package/lib/inbox/{InboxLogic.js → inboxLogic.js} +58 -64
- package/lib/inbox/inboxLogic.js.map +1 -0
- package/lib/index.d.ts +18 -9
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +86 -22
- package/lib/index.js.map +1 -1
- package/lib/logic/CustomError.d.ts +4 -0
- package/lib/logic/CustomError.d.ts.map +1 -1
- package/lib/logic/CustomError.js +17 -1
- package/lib/logic/CustomError.js.map +1 -1
- package/lib/logic/SolidLogic.d.ts +8 -34
- package/lib/logic/SolidLogic.d.ts.map +1 -1
- package/lib/logic/SolidLogic.js +16 -250
- package/lib/logic/SolidLogic.js.map +1 -1
- package/lib/logic/solidLogicSingleton.js +1 -1
- package/lib/logic/solidLogicSingleton.js.map +1 -1
- package/lib/logic/solidLogicSingletonNew.d.ts +80 -0
- package/lib/logic/solidLogicSingletonNew.d.ts.map +1 -0
- package/lib/logic/solidLogicSingletonNew.js +238 -0
- package/lib/logic/solidLogicSingletonNew.js.map +1 -0
- package/lib/profile/profileLogic.d.ts +13 -0
- package/lib/profile/profileLogic.d.ts.map +1 -0
- package/lib/profile/profileLogic.js +268 -0
- package/lib/profile/profileLogic.js.map +1 -0
- package/lib/typeIndex/typeIndexLogic.d.ts +31 -21
- package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -1
- package/lib/typeIndex/typeIndexLogic.js +650 -295
- package/lib/typeIndex/typeIndexLogic.js.map +1 -1
- package/lib/types.d.ts +17 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/util/containerLogic.d.ts +11 -0
- package/lib/util/containerLogic.d.ts.map +1 -0
- package/lib/{profile/ProfileLogic.js → util/containerLogic.js} +53 -44
- package/lib/util/containerLogic.js.map +1 -0
- package/lib/util/ns.d.ts +2 -0
- package/lib/util/ns.d.ts.map +1 -0
- package/lib/util/ns.js +34 -0
- package/lib/util/ns.js.map +1 -0
- package/lib/util/utilityLogic.d.ts +15 -0
- package/lib/util/utilityLogic.d.ts.map +1 -0
- package/lib/util/utilityLogic.js +272 -0
- package/lib/util/utilityLogic.js.map +1 -0
- package/lib/util/utils.d.ts +8 -0
- package/lib/util/utils.d.ts.map +1 -0
- package/lib/util/utils.js +48 -0
- package/lib/util/utils.js.map +1 -0
- package/package.json +3 -1
- package/src/acl/aclLogic.ts +136 -118
- package/src/authn/SolidAuthnLogic.ts +3 -2
- package/src/chat/chatLogic.ts +225 -0
- package/src/inbox/inboxLogic.ts +57 -0
- package/src/index.ts +142 -18
- package/src/logic/CustomError.ts +5 -1
- package/src/logic/SolidLogic.ts +30 -211
- package/src/logic/solidLogicSingleton.ts +1 -1
- package/src/logic/solidLogicSingletonNew.ts +239 -0
- package/src/profile/profileLogic.ts +134 -0
- package/src/typeIndex/typeIndexLogic.ts +417 -153
- package/src/types.ts +7 -3
- package/src/util/containerLogic.ts +54 -0
- package/src/util/ns.ts +5 -0
- package/src/util/utilityLogic.ts +155 -0
- package/src/util/utils.ts +52 -0
- package/test/aclLogic.test.ts +13 -4
- package/test/chatLogic.test.ts +70 -71
- package/test/container.test.ts +56 -0
- package/test/helpers/dataSetup.ts +134 -0
- package/test/helpers/setup.ts +1 -0
- package/test/inboxLogic.test.ts +39 -38
- package/test/logic.test.ts +10 -9
- package/test/profileLogic.test.ts +246 -0
- package/test/typeIndexLogic.test.ts +49 -22
- package/test/typeIndexLogicPart2.test.ts +485 -0
- package/test/utilityLogic.test.ts +172 -126
- package/test/utils.test.ts +32 -0
- package/lib/chat/ChatLogic.d.ts +0 -26
- package/lib/chat/ChatLogic.d.ts.map +0 -1
- package/lib/chat/ChatLogic.js.map +0 -1
- package/lib/chat/determineChatContainer.d.ts +0 -3
- package/lib/chat/determineChatContainer.d.ts.map +0 -1
- package/lib/chat/determineChatContainer.js +0 -12
- package/lib/chat/determineChatContainer.js.map +0 -1
- package/lib/discovery/discoveryLogic.d.ts +0 -40
- package/lib/discovery/discoveryLogic.d.ts.map +0 -1
- package/lib/discovery/discoveryLogic.js +0 -494
- package/lib/discovery/discoveryLogic.js.map +0 -1
- package/lib/inbox/InboxLogic.d.ts +0 -18
- package/lib/inbox/InboxLogic.d.ts.map +0 -1
- package/lib/inbox/InboxLogic.js.map +0 -1
- package/lib/profile/ProfileLogic.d.ts +0 -13
- package/lib/profile/ProfileLogic.d.ts.map +0 -1
- package/lib/profile/ProfileLogic.js.map +0 -1
- package/lib/util/UtilityLogic.d.ts +0 -33
- package/lib/util/UtilityLogic.d.ts.map +0 -1
- package/lib/util/UtilityLogic.js +0 -240
- package/lib/util/UtilityLogic.js.map +0 -1
- package/lib/util/uri.d.ts +0 -3
- package/lib/util/uri.d.ts.map +0 -1
- package/lib/util/uri.js +0 -9
- package/lib/util/uri.js.map +0 -1
- package/src/chat/ChatLogic.ts +0 -244
- package/src/chat/determineChatContainer.ts +0 -14
- package/src/discovery/discoveryLogic.ts +0 -311
- package/src/inbox/InboxLogic.ts +0 -66
- package/src/profile/ProfileLogic.ts +0 -44
- package/src/util/UtilityLogic.ts +0 -161
- package/src/util/uri.ts +0 -5
- package/test/discoveryLogic.test.ts +0 -740
|
@@ -1,117 +1,176 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import * as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { solidLogicSingleton } from "../logic/solidLogicSingleton"
|
|
8
|
-
// import { ensureLoadedPreferences } from '../logic/logic'
|
|
9
|
-
import { loadPreferences, loadProfile } from '../discovery/discoveryLogic'
|
|
10
|
-
export const ns = solidNamespace($rdf)
|
|
11
|
-
|
|
12
|
-
const store = solidLogicSingleton.store
|
|
13
|
-
|
|
14
|
-
async function ensureLoadedPreferences (context:AuthenticationContext) {
|
|
15
|
-
if (!context.me) throw new Error('@@ ensureLoadedPreferences: no user specified')
|
|
16
|
-
context.publicProfile = await loadProfile(store, context.me)
|
|
17
|
-
context.preferencesFile = await loadPreferences(store, context.me)
|
|
18
|
-
return context
|
|
19
|
-
}
|
|
1
|
+
import * as rdf from "rdflib"
|
|
2
|
+
import { NamedNode, st, Statement, sym } from 'rdflib'
|
|
3
|
+
import { AuthenticationContext, ScopedApp, TypeIndexScope } from '../types'
|
|
4
|
+
import * as debug from "../util/debug"
|
|
5
|
+
import {ns as namespace } from '../util/ns'
|
|
6
|
+
import { newThing, uniqueNodes } from "../util/utils"
|
|
20
7
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
8
|
+
export function createTypeIndexLogic(store, authn, profileLogic, utilityLogic) {
|
|
9
|
+
const ns = namespace
|
|
10
|
+
|
|
11
|
+
function updatePromise(
|
|
12
|
+
del: Array<Statement>,
|
|
13
|
+
ins: Array<Statement> = []
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
store.updater.update(del, ins, function (_uri, ok, errorBody) {
|
|
17
|
+
if (!ok) {
|
|
18
|
+
reject(new Error(errorBody));
|
|
19
|
+
} else {
|
|
20
|
+
resolve();
|
|
21
|
+
}
|
|
22
|
+
}); // callback
|
|
23
|
+
}); // promise
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolves with the same context, outputting
|
|
27
|
+
* @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
|
|
28
|
+
*/
|
|
29
|
+
async function ensureTypeIndexes(context: AuthenticationContext, agent?: NamedNode): Promise<AuthenticationContext> {
|
|
30
|
+
if (!context.me) {
|
|
31
|
+
throw new Error(`ensureTypeIndexes: @@ no user`)
|
|
32
|
+
}
|
|
33
|
+
await ensureOneTypeIndex(context, true, agent)
|
|
34
|
+
await ensureOneTypeIndex(context, false, agent)
|
|
35
|
+
return context
|
|
36
|
+
}
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
async function loadTypeIndexes(context: AuthenticationContext) {
|
|
39
|
+
try {
|
|
40
|
+
await profileLogic.silencedLoadPreferences(context.me as NamedNode)
|
|
41
|
+
} catch (error) {
|
|
42
|
+
debug.warn(error.message) as undefined
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const indexes = await loadIndexes(
|
|
46
|
+
context.me as NamedNode,
|
|
47
|
+
context.publicProfile || null,
|
|
48
|
+
context.preferencesFile || null,
|
|
49
|
+
// async (err: Error) => widgets.complain(context, err.message)
|
|
50
|
+
// async (err: Error) => debug.warn(err.message) as undefined
|
|
51
|
+
)
|
|
52
|
+
context.index = context.index || {}
|
|
53
|
+
context.index.private = indexes.private || context.index.private
|
|
54
|
+
context.index.public = indexes.public || context.index.public
|
|
55
|
+
return context
|
|
56
|
+
} catch (error) {
|
|
57
|
+
async (error: Error) => debug.warn(error.message) as undefined
|
|
58
|
+
}
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Register a new app in a type index
|
|
63
|
+
* used in chat in bookmark.js (solid-ui)
|
|
64
|
+
*/
|
|
65
|
+
async function registerInTypeIndex(
|
|
66
|
+
context: AuthenticationContext,
|
|
67
|
+
instance: NamedNode,
|
|
68
|
+
theClass: NamedNode,
|
|
69
|
+
isPublic: boolean,
|
|
70
|
+
agent?: NamedNode // Defaults to current user
|
|
71
|
+
): Promise<AuthenticationContext> {
|
|
72
|
+
await ensureOneTypeIndex(context, isPublic, agent)
|
|
73
|
+
if (!context.index) {
|
|
74
|
+
throw new Error('registerInTypeIndex: No type index found')
|
|
75
|
+
}
|
|
76
|
+
const indexes = isPublic ? context.index.public : context.index.private
|
|
77
|
+
if (!indexes.length) {
|
|
78
|
+
throw new Error('registerInTypeIndex: What no type index?')
|
|
79
|
+
}
|
|
80
|
+
const index = indexes[0]
|
|
81
|
+
const registration = newThing(index)
|
|
82
|
+
const ins = [
|
|
83
|
+
// See https://github.com/solidos/solid/blob/main/proposals/data-discovery.md
|
|
84
|
+
st(registration, ns.rdf('type'), ns.solid('TypeRegistration'), index),
|
|
85
|
+
st(registration, ns.solid('forClass'), theClass, index),
|
|
86
|
+
st(registration, ns.solid('instance'), instance, index)
|
|
87
|
+
]
|
|
88
|
+
try {
|
|
89
|
+
await updatePromise([], ins)
|
|
90
|
+
} catch (e) {
|
|
91
|
+
debug.log(e)
|
|
92
|
+
alert(e)
|
|
93
|
+
}
|
|
94
|
+
return context
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resolves with the same context, outputting
|
|
99
|
+
* output: index.public, index.private
|
|
100
|
+
* @@ This is a very bizare function
|
|
101
|
+
* @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
|
|
102
|
+
*/
|
|
103
|
+
async function loadIndex(
|
|
104
|
+
context: AuthenticationContext,
|
|
105
|
+
isPublic: boolean
|
|
106
|
+
): Promise<AuthenticationContext> {
|
|
107
|
+
const indexes = await loadIndexes(
|
|
52
108
|
context.me as NamedNode,
|
|
53
|
-
context.publicProfile || null,
|
|
54
|
-
context.preferencesFile || null,
|
|
109
|
+
(isPublic ? context.publicProfile || null : null),
|
|
110
|
+
(isPublic ? null : context.preferencesFile || null),
|
|
55
111
|
// async (err: Error) => widgets.complain(context, err.message)
|
|
56
|
-
|
|
112
|
+
async (err: Error) => debug.error(err.message) as undefined
|
|
57
113
|
)
|
|
58
114
|
context.index = context.index || {}
|
|
59
|
-
context.index.private = indexes.private
|
|
60
|
-
context.index.public = indexes.public
|
|
115
|
+
context.index.private = indexes.private.concat(context.index.private || []) // otherwise concat will wrongly add 'undefined' as a private index
|
|
116
|
+
context.index.public = indexes.public.concat(context.index.public || []) // otherwise concat will wrongly add 'undefined' as a public index
|
|
61
117
|
return context
|
|
62
|
-
} catch (error) {
|
|
63
|
-
async (error: Error) => debug.warn(error.message) as undefined
|
|
64
118
|
}
|
|
65
|
-
}
|
|
66
119
|
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
await ensureOneTypeIndex(context, false, agent)
|
|
77
|
-
return context
|
|
78
|
-
}
|
|
120
|
+
/**
|
|
121
|
+
* Load or create ONE type index
|
|
122
|
+
* Find one or make one or fail
|
|
123
|
+
* Many reasons for failing including script not having permission etc
|
|
124
|
+
*
|
|
125
|
+
* Adds its output to the context
|
|
126
|
+
* @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
|
|
127
|
+
*/
|
|
128
|
+
async function ensureOneTypeIndex(context: AuthenticationContext, isPublic: boolean, agent?: NamedNode): Promise<AuthenticationContext | void> {
|
|
79
129
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
*
|
|
85
|
-
* Adds its output to the context
|
|
86
|
-
* @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
|
|
87
|
-
*/
|
|
88
|
-
async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boolean, agent?: NamedNode): Promise<AuthenticationContext | void> {
|
|
89
|
-
async function makeIndexIfNecessary (context, isPublic) {
|
|
90
|
-
const relevant = isPublic ? context.publicProfile : context.preferencesFile
|
|
91
|
-
if (!relevant) alert ('@@@@ relevent null')
|
|
92
|
-
const visibility = isPublic ? 'public' : 'private'
|
|
130
|
+
const context2 = await profileLogic.ensureLoadedPreferences(context)
|
|
131
|
+
if (!context2.publicProfile) throw new Error(`@@ type index: no publicProfile`)
|
|
132
|
+
if (!context2.preferencesFile) throw new Error(`@@ type index: no preferencesFile for profile ${context2.publicProfile}`)
|
|
133
|
+
const relevant = isPublic ? context2.publicProfile : context2.preferencesFile
|
|
93
134
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
// widgets.complain(context, msg)
|
|
101
|
-
debug.warn(msg)
|
|
135
|
+
try {
|
|
136
|
+
await loadIndex(context2, isPublic)
|
|
137
|
+
const pp = isPublic ? 'public' : 'private'
|
|
138
|
+
if (context2.index && context2.index[pp] && context2.index[pp].length > 0) {
|
|
139
|
+
debug.log(`ensureOneTypeIndex: Type index exists already ${context2.index[pp]}`)
|
|
140
|
+
return context2
|
|
102
141
|
}
|
|
103
|
-
|
|
142
|
+
await makeIndexIfNecessary(context2, isPublic, store, ns)
|
|
143
|
+
} catch (error) {
|
|
144
|
+
await makeIndexIfNecessary(context2, isPublic, store, ns)
|
|
145
|
+
// widgets.complain(context2, 'calling loadIndex:' + error)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
104
148
|
|
|
149
|
+
async function putIndex(newIndex, context) {
|
|
150
|
+
try {
|
|
151
|
+
await utilityLogic.createEmptyRdfDoc(newIndex, 'Blank initial Type index')
|
|
152
|
+
return context
|
|
153
|
+
} catch (e) {
|
|
154
|
+
const msg = `Error creating new index ${e}`
|
|
155
|
+
// widgets.complain(context, msg)
|
|
156
|
+
debug.warn(msg)
|
|
157
|
+
}
|
|
158
|
+
} // putIndex
|
|
159
|
+
|
|
160
|
+
async function makeIndexIfNecessary(context, isPublic, store, ns) {
|
|
161
|
+
const relevant = isPublic ? context.publicProfile : context.preferencesFile
|
|
162
|
+
if (!relevant) alert('@@@@ relevent null')
|
|
163
|
+
const visibility = isPublic ? 'public' : 'private'
|
|
105
164
|
|
|
106
165
|
context.index = context.index || {}
|
|
107
166
|
context.index[visibility] = context.index[visibility] || []
|
|
108
167
|
let newIndex
|
|
109
168
|
if (context.index[visibility].length === 0) {
|
|
110
169
|
if (!store.updater.editable(relevant)) {
|
|
111
|
-
|
|
112
|
-
|
|
170
|
+
debug.log(`Not adding new type index as ${relevant} is not editable`)
|
|
171
|
+
return
|
|
113
172
|
}
|
|
114
|
-
newIndex = sym(`${relevant.dir().uri + visibility}TypeIndex.ttl`)
|
|
173
|
+
newIndex = rdf.sym(`${relevant.dir().uri + visibility}TypeIndex.ttl`)
|
|
115
174
|
debug.log(`Linking to new fresh type index ${newIndex}`)
|
|
116
175
|
if (!confirm(`OK to create a new empty index file at ${newIndex}, overwriting anything that is now there?`)) {
|
|
117
176
|
throw new Error('cancelled by user')
|
|
@@ -121,7 +180,7 @@ async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boo
|
|
|
121
180
|
st(context.me, ns.solid(`${visibility}TypeIndex`), newIndex, relevant)
|
|
122
181
|
]
|
|
123
182
|
try {
|
|
124
|
-
await
|
|
183
|
+
await updatePromise([], addMe)
|
|
125
184
|
} catch (err) {
|
|
126
185
|
const msg = `Error saving type index link saving back ${newIndex}: ${err}`
|
|
127
186
|
//widgets.complain(context, msg)
|
|
@@ -130,72 +189,277 @@ async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boo
|
|
|
130
189
|
}
|
|
131
190
|
|
|
132
191
|
debug.log(`Creating new fresh type index file${newIndex}`)
|
|
133
|
-
await putIndex(newIndex)
|
|
192
|
+
await putIndex(newIndex, context)
|
|
134
193
|
context.index[visibility].push(newIndex) // @@ wait
|
|
135
194
|
} else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
195
|
+
// officially exists
|
|
196
|
+
const ixs = context.index[visibility]
|
|
197
|
+
try {
|
|
198
|
+
await store.fetcher.load(ixs)
|
|
199
|
+
} catch (err) {
|
|
200
|
+
const msg = `ensureOneTypeIndex: loading indexes ${err}`
|
|
201
|
+
debug.warn(msg)
|
|
202
|
+
// widgets.complain(context, `ensureOneTypeIndex: loading indexes ${err}`)
|
|
203
|
+
}
|
|
145
204
|
}
|
|
146
205
|
} // makeIndexIfNecessary
|
|
147
206
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
207
|
+
async function loadIndexes(
|
|
208
|
+
me: NamedNode | string,
|
|
209
|
+
publicProfile: NamedNode | string | null,
|
|
210
|
+
preferencesFile: NamedNode | string | null,
|
|
211
|
+
onWarning = async (_err: Error) => {
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
): Promise<{
|
|
215
|
+
private: any;
|
|
216
|
+
public: any;
|
|
217
|
+
}> {
|
|
218
|
+
let privateIndexes: any[] = [];
|
|
219
|
+
let publicIndexes: any[] = [];
|
|
220
|
+
if (publicProfile) {
|
|
221
|
+
publicIndexes = getTypeIndex(me, publicProfile, true);
|
|
222
|
+
try {
|
|
223
|
+
await store.fetcher.load(publicIndexes as NamedNode[]);
|
|
224
|
+
} catch (err) {
|
|
225
|
+
onWarning(new Error(`loadIndex: loading public type index(es) ${err}`));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (preferencesFile) {
|
|
229
|
+
privateIndexes = getTypeIndex(me, preferencesFile, false);
|
|
230
|
+
// console.log({ privateIndexes })
|
|
231
|
+
if (privateIndexes.length === 0) {
|
|
232
|
+
await onWarning(
|
|
233
|
+
new Error(
|
|
234
|
+
`Your preference file ${preferencesFile} does not point to a private type index.`
|
|
235
|
+
)
|
|
236
|
+
);
|
|
237
|
+
} else {
|
|
238
|
+
try {
|
|
239
|
+
await store.fetcher.load(privateIndexes);
|
|
240
|
+
} catch (err) {
|
|
241
|
+
onWarning(
|
|
242
|
+
new Error(`loadIndex: loading private type index(es) ${err}`)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// } else {
|
|
247
|
+
// debug.log(
|
|
248
|
+
// 'We know your preference file is not available, so we are not bothering with private type indexes.'
|
|
249
|
+
// )
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
private: privateIndexes,
|
|
254
|
+
public: publicIndexes,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
152
257
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
258
|
+
function getTypeIndex(
|
|
259
|
+
me: NamedNode | string,
|
|
260
|
+
preferencesFile: NamedNode | string,
|
|
261
|
+
isPublic: boolean
|
|
262
|
+
): NamedNode[] {
|
|
263
|
+
// console.log('getTypeIndex', store.each(me, undefined, undefined, preferencesFile), isPublic, preferencesFile)
|
|
264
|
+
return store.each(
|
|
265
|
+
me as NamedNode,
|
|
266
|
+
isPublic ? ns.solid("publicTypeIndex") : ns.solid("privateTypeIndex"),
|
|
267
|
+
undefined,
|
|
268
|
+
preferencesFile as NamedNode
|
|
269
|
+
) as NamedNode[];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function getRegistrations(instance, theClass) {
|
|
273
|
+
return store
|
|
274
|
+
.each(undefined, ns.solid("instance"), instance)
|
|
275
|
+
.filter((r) => {
|
|
276
|
+
return store.holds(r, ns.solid("forClass"), theClass);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async function loadTypeIndexesFor(user: NamedNode): Promise<Array<TypeIndexScope>> {
|
|
281
|
+
if (!user) throw new Error(`loadTypeIndexesFor: No user given`)
|
|
282
|
+
const profile = await profileLogic.loadProfile(user)
|
|
283
|
+
|
|
284
|
+
const suggestion = suggestPublicTypeIndex(user)
|
|
285
|
+
let publicTypeIndex
|
|
286
|
+
try {
|
|
287
|
+
publicTypeIndex = await utilityLogic.followOrCreateLink(user, ns.solid('publicTypeIndex') as NamedNode, suggestion, profile)
|
|
288
|
+
} catch (err) {
|
|
289
|
+
const message = `User ${user} has no pointer in profile to publicTypeIndex file.`
|
|
290
|
+
debug.warn(message)
|
|
159
291
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
292
|
+
const publicScopes = publicTypeIndex ? [{ label: 'public', index: publicTypeIndex as NamedNode, agent: user }] : []
|
|
293
|
+
|
|
294
|
+
let preferencesFile
|
|
295
|
+
try {
|
|
296
|
+
preferencesFile = await profileLogic.silencedLoadPreferences(user)
|
|
297
|
+
} catch (err) {
|
|
298
|
+
preferencesFile = null
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
let privateScopes
|
|
302
|
+
if (preferencesFile) { // watch out - can be in either as spec was not clear. Legacy is profile.
|
|
303
|
+
// If there is a legacy one linked from the profile, use that.
|
|
304
|
+
// Otherwiae use or make one linked from Preferences
|
|
305
|
+
const suggestedPrivateTypeIndex = suggestPrivateTypeIndex(preferencesFile)
|
|
306
|
+
let privateTypeIndex
|
|
307
|
+
try {
|
|
308
|
+
privateTypeIndex = store.any(user, ns.solid('privateTypeIndex'), undefined, profile) ||
|
|
309
|
+
await utilityLogic.followOrCreateLink(user, ns.solid('privateTypeIndex') as NamedNode, suggestedPrivateTypeIndex, preferencesFile);
|
|
310
|
+
} catch (err) {
|
|
311
|
+
const message = `User ${user} has no pointer in preference file to privateTypeIndex file.`
|
|
312
|
+
debug.warn(message)
|
|
313
|
+
}
|
|
314
|
+
privateScopes = privateTypeIndex ? [{ label: 'private', index: privateTypeIndex as NamedNode, agent: user }] : []
|
|
315
|
+
} else {
|
|
316
|
+
privateScopes = []
|
|
317
|
+
}
|
|
318
|
+
const scopes = publicScopes.concat(privateScopes)
|
|
319
|
+
if (scopes.length === 0) return scopes
|
|
320
|
+
const files = scopes.map(scope => scope.index)
|
|
321
|
+
try {
|
|
322
|
+
await store.fetcher.load(files)
|
|
323
|
+
} catch (err) {
|
|
324
|
+
debug.warn('Problems loading type index: ', err)
|
|
325
|
+
}
|
|
326
|
+
return scopes
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
async function loadCommunityTypeIndexes(user: NamedNode): Promise<TypeIndexScope[][]> {
|
|
330
|
+
let preferencesFile
|
|
331
|
+
try {
|
|
332
|
+
preferencesFile = await profileLogic.silencedLoadPreferences(user)
|
|
333
|
+
} catch (err) {
|
|
334
|
+
const message = `User ${user} has no pointer in profile to preferences file.`
|
|
335
|
+
debug.warn(message)
|
|
336
|
+
}
|
|
337
|
+
if (preferencesFile) { // For now, pick up communities as simple links from the preferences file.
|
|
338
|
+
const communities = store.each(user, ns.solid('community'), undefined, preferencesFile as NamedNode).concat(
|
|
339
|
+
store.each(user, ns.solid('community'), undefined, user.doc() as NamedNode)
|
|
340
|
+
)
|
|
341
|
+
let result = []
|
|
342
|
+
for (const org of communities) {
|
|
343
|
+
result = result.concat(await loadTypeIndexesFor(org as NamedNode) as any)
|
|
344
|
+
}
|
|
345
|
+
return result
|
|
346
|
+
}
|
|
347
|
+
return [] // No communities
|
|
164
348
|
}
|
|
165
|
-
}
|
|
166
349
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
350
|
+
async function loadAllTypeIndexes(user: NamedNode) {
|
|
351
|
+
return (await loadTypeIndexesFor(user)).concat((await loadCommunityTypeIndexes(user)).flat())
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async function getScopedAppInstances(klass: NamedNode, user: NamedNode): Promise<ScopedApp[]> {
|
|
355
|
+
const scopes = await loadAllTypeIndexes(user)
|
|
356
|
+
let scopedApps = []
|
|
357
|
+
for (const scope of scopes) {
|
|
358
|
+
const scopedApps0 = await getScopedAppsFromIndex(scope, klass) as any
|
|
359
|
+
scopedApps = scopedApps.concat(scopedApps0)
|
|
360
|
+
}
|
|
361
|
+
return scopedApps
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// This is the function signature which used to be in solid-ui/logic
|
|
365
|
+
// Recommended to use getScopedAppInstances instead as it provides more information.
|
|
366
|
+
//
|
|
367
|
+
async function getAppInstances(klass: NamedNode): Promise<NamedNode[]> {
|
|
368
|
+
const user = authn.currentUser()
|
|
369
|
+
if (!user) throw new Error('getAppInstances: Must be logged in to find apps.')
|
|
370
|
+
const scopedAppInstances = await getScopedAppInstances(klass, user)
|
|
371
|
+
return scopedAppInstances.map(scoped => scoped.instance)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function suggestPublicTypeIndex(me: NamedNode) {
|
|
375
|
+
return sym(me.doc().dir()?.uri + 'publicTypeIndex.ttl')
|
|
376
|
+
}
|
|
377
|
+
// Note this one is based off the pref file not the profile
|
|
378
|
+
|
|
379
|
+
function suggestPrivateTypeIndex(preferencesFile: NamedNode) {
|
|
380
|
+
return sym(preferencesFile.doc().dir()?.uri + 'privateTypeIndex.ttl')
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/*
|
|
384
|
+
* Register a new app in a type index
|
|
385
|
+
* used in chat in bookmark.js (solid-ui)
|
|
386
|
+
* Returns the registration object if successful else null
|
|
387
|
+
*/
|
|
388
|
+
async function registerInstanceInTypeIndex(
|
|
389
|
+
instance: NamedNode,
|
|
390
|
+
index: NamedNode,
|
|
391
|
+
theClass: NamedNode,
|
|
392
|
+
// agent: NamedNode
|
|
393
|
+
): Promise<NamedNode | null> {
|
|
394
|
+
const registration = newThing(index)
|
|
395
|
+
const ins = [
|
|
396
|
+
// See https://github.com/solid/solid/blob/main/proposals/data-discovery.md
|
|
397
|
+
st(registration, ns.rdf('type'), ns.solid('TypeRegistration'), index),
|
|
398
|
+
st(registration, ns.solid('forClass'), theClass, index),
|
|
399
|
+
st(registration, ns.solid('instance'), instance, index)
|
|
400
|
+
]
|
|
401
|
+
try {
|
|
402
|
+
await store.updater.update([], ins)
|
|
403
|
+
} catch (err) {
|
|
404
|
+
const msg = `Unable to register ${instance} in index ${index}: ${err}`
|
|
405
|
+
console.warn(msg)
|
|
406
|
+
return null
|
|
407
|
+
}
|
|
408
|
+
return registration
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async function deleteTypeIndexRegistration(item) {
|
|
412
|
+
const reg = store.the(null, ns.solid('instance'), item.instance, item.scope.index) as NamedNode
|
|
413
|
+
if (!reg) throw new Error(`deleteTypeIndexRegistration: No registration found for ${item.instance}`)
|
|
414
|
+
const statements = store.statementsMatching(reg, null, null, item.scope.index)
|
|
415
|
+
await store.updater.update(statements, [])
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
async function getScopedAppsFromIndex(scope, theClass: NamedNode | null) {
|
|
419
|
+
const index = scope.index
|
|
420
|
+
const registrations = store.statementsMatching(null, ns.solid('instance'), null, index)
|
|
421
|
+
.concat(store.statementsMatching(null, ns.solid('instanceContainer'), null, index))
|
|
422
|
+
.map(st => st.subject)
|
|
423
|
+
const relevant = theClass ? registrations.filter(reg => store.any(reg, ns.solid('forClass'), null, index)?.sameTerm(theClass))
|
|
424
|
+
: registrations
|
|
425
|
+
const directInstances = relevant.map(reg => store.each(reg, ns.solid('instance'), null, index).map(one => sym(one.value))).flat()
|
|
426
|
+
let instances = uniqueNodes(directInstances)
|
|
427
|
+
|
|
428
|
+
const instanceContainers = relevant.map(
|
|
429
|
+
reg => store.each(reg, ns.solid('instanceContainer'), null, index).map(one => sym(one.value))).flat()
|
|
430
|
+
|
|
431
|
+
// instanceContainers may be deprocatable if no one has used them
|
|
432
|
+
const containers = uniqueNodes(instanceContainers)
|
|
433
|
+
if (containers.length > 0) { console.log('@@ getScopedAppsFromIndex containers ', containers) }
|
|
434
|
+
for (let i = 0; i < containers.length; i++) {
|
|
435
|
+
const cont = containers[i]
|
|
436
|
+
await store.fetcher.load(cont)
|
|
437
|
+
const contents = store.each(cont, ns.ldp('contains'), null, cont).map(one => sym(one.value))
|
|
438
|
+
instances = instances.concat(contents)
|
|
439
|
+
}
|
|
440
|
+
return instances.map(instance => { return { instance, scope } })
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return {
|
|
444
|
+
ensureTypeIndexes,
|
|
445
|
+
loadTypeIndexes,
|
|
446
|
+
registerInTypeIndex,
|
|
447
|
+
loadIndex,
|
|
448
|
+
ensureOneTypeIndex,
|
|
449
|
+
putIndex,
|
|
450
|
+
makeIndexIfNecessary,
|
|
451
|
+
loadIndexes,
|
|
452
|
+
getTypeIndex,
|
|
453
|
+
getRegistrations,
|
|
454
|
+
loadTypeIndexesFor,
|
|
455
|
+
loadCommunityTypeIndexes,
|
|
456
|
+
loadAllTypeIndexes,
|
|
457
|
+
getScopedAppInstances,
|
|
458
|
+
getAppInstances,
|
|
459
|
+
suggestPublicTypeIndex,
|
|
460
|
+
suggestPrivateTypeIndex,
|
|
461
|
+
registerInstanceInTypeIndex,
|
|
462
|
+
deleteTypeIndexRegistration,
|
|
463
|
+
getScopedAppsFromIndex
|
|
464
|
+
}
|
|
201
465
|
}
|
package/src/types.ts
CHANGED
|
@@ -32,12 +32,16 @@ export interface SolidNamespace {
|
|
|
32
32
|
[key: string]: (term: string) => NamedNode
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
export type TypeIndexScope = { label: string, index: NamedNode, agent: NamedNode }
|
|
36
|
+
export type ScopedApp = { instance: NamedNode, scope: TypeIndexScope }
|
|
37
|
+
|
|
38
|
+
export interface NewPaneOptions {
|
|
36
39
|
me?: NamedNode;
|
|
37
40
|
newInstance?: NamedNode;
|
|
38
41
|
newBase: string;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
interface CreatedPaneOptions {
|
|
44
|
+
export interface CreatedPaneOptions {
|
|
42
45
|
newInstance: NamedNode;
|
|
43
|
-
}
|
|
46
|
+
}
|
|
47
|
+
|