solid-logic 1.3.17-9d25ceb7 → 1.3.17-a849582e

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 (114) hide show
  1. package/lib/acl/aclLogic.d.ts +12 -30
  2. package/lib/acl/aclLogic.d.ts.map +1 -1
  3. package/lib/acl/aclLogic.js +151 -116
  4. package/lib/acl/aclLogic.js.map +1 -1
  5. package/lib/authn/SolidAuthnLogic.d.ts.map +1 -1
  6. package/lib/authn/SolidAuthnLogic.js +2 -2
  7. package/lib/authn/SolidAuthnLogic.js.map +1 -1
  8. package/lib/chat/chatLogic.d.ts +16 -0
  9. package/lib/chat/chatLogic.d.ts.map +1 -0
  10. package/lib/chat/{ChatLogic.js → chatLogic.js} +82 -87
  11. package/lib/chat/chatLogic.js.map +1 -0
  12. package/lib/discovery/discoveryLogic.d.ts +8 -8
  13. package/lib/discovery/discoveryLogic.d.ts.map +1 -1
  14. package/lib/discovery/discoveryLogic.js +65 -72
  15. package/lib/discovery/discoveryLogic.js.map +1 -1
  16. package/lib/inbox/inboxLogic.d.ts +7 -0
  17. package/lib/inbox/inboxLogic.d.ts.map +1 -0
  18. package/lib/inbox/{InboxLogic.js → inboxLogic.js} +58 -64
  19. package/lib/inbox/inboxLogic.js.map +1 -0
  20. package/lib/index.d.ts +10 -13
  21. package/lib/index.d.ts.map +1 -1
  22. package/lib/index.js +76 -32
  23. package/lib/index.js.map +1 -1
  24. package/lib/logic/CustomError.d.ts +4 -0
  25. package/lib/logic/CustomError.d.ts.map +1 -1
  26. package/lib/logic/CustomError.js +17 -1
  27. package/lib/logic/CustomError.js.map +1 -1
  28. package/lib/logic/solidLogicSingleton.d.ts +35 -3
  29. package/lib/logic/solidLogicSingleton.d.ts.map +1 -1
  30. package/lib/logic/solidLogicSingleton.js +87 -8
  31. package/lib/logic/solidLogicSingleton.js.map +1 -1
  32. package/lib/profile/profileLogic.d.ts +13 -0
  33. package/lib/profile/profileLogic.d.ts.map +1 -0
  34. package/lib/profile/profileLogic.js +268 -0
  35. package/lib/profile/profileLogic.js.map +1 -0
  36. package/lib/typeIndex/typeIndexLogic.d.ts +31 -21
  37. package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -1
  38. package/lib/typeIndex/typeIndexLogic.js +650 -295
  39. package/lib/typeIndex/typeIndexLogic.js.map +1 -1
  40. package/lib/types.d.ts +17 -0
  41. package/lib/types.d.ts.map +1 -1
  42. package/lib/util/containerLogic.d.ts +11 -0
  43. package/lib/util/containerLogic.d.ts.map +1 -0
  44. package/lib/{profile/ProfileLogic.js → util/containerLogic.js} +53 -44
  45. package/lib/util/containerLogic.js.map +1 -0
  46. package/lib/util/utilityLogic.d.ts +15 -0
  47. package/lib/util/utilityLogic.d.ts.map +1 -0
  48. package/lib/util/utilityLogic.js +272 -0
  49. package/lib/util/utilityLogic.js.map +1 -0
  50. package/lib/util/utils.d.ts +8 -0
  51. package/lib/util/utils.d.ts.map +1 -0
  52. package/lib/util/utils.js +48 -0
  53. package/lib/util/utils.js.map +1 -0
  54. package/package.json +3 -1
  55. package/src/acl/aclLogic.ts +135 -119
  56. package/src/authn/SolidAuthnLogic.ts +3 -2
  57. package/src/chat/chatLogic.ts +225 -0
  58. package/src/discovery/discoveryLogic.ts +66 -87
  59. package/src/inbox/inboxLogic.ts +57 -0
  60. package/src/index.ts +74 -21
  61. package/src/logic/CustomError.ts +5 -1
  62. package/src/logic/solidLogicSingleton.ts +160 -7
  63. package/src/profile/profileLogic.ts +134 -0
  64. package/src/typeIndex/typeIndexLogic.ts +417 -153
  65. package/src/types.ts +7 -3
  66. package/src/util/containerLogic.ts +54 -0
  67. package/src/util/ns.js +5 -0
  68. package/src/util/utilityLogic.ts +155 -0
  69. package/src/util/utils.ts +52 -0
  70. package/test/aclLogic.test.ts +13 -4
  71. package/test/chatLogic.test.ts +70 -71
  72. package/test/container.test.ts +56 -0
  73. package/test/discoveryLogic.test.ts +14 -14
  74. package/test/helpers/dataSetup.ts +134 -0
  75. package/test/helpers/setup.ts +4 -0
  76. package/test/inboxLogic.test.ts +39 -38
  77. package/test/logic.test.ts +11 -9
  78. package/test/profileLogic.test.ts +246 -0
  79. package/test/typeIndexLogic.test.ts +49 -22
  80. package/test/typeIndexLogicPart2.test.ts +485 -0
  81. package/test/utilityLogic.test.ts +172 -126
  82. package/test/utils.test.ts +32 -0
  83. package/lib/chat/ChatLogic.d.ts +0 -26
  84. package/lib/chat/ChatLogic.d.ts.map +0 -1
  85. package/lib/chat/ChatLogic.js.map +0 -1
  86. package/lib/chat/determineChatContainer.d.ts +0 -3
  87. package/lib/chat/determineChatContainer.d.ts.map +0 -1
  88. package/lib/chat/determineChatContainer.js +0 -12
  89. package/lib/chat/determineChatContainer.js.map +0 -1
  90. package/lib/inbox/InboxLogic.d.ts +0 -18
  91. package/lib/inbox/InboxLogic.d.ts.map +0 -1
  92. package/lib/inbox/InboxLogic.js.map +0 -1
  93. package/lib/logic/SolidLogic.d.ts +0 -48
  94. package/lib/logic/SolidLogic.d.ts.map +0 -1
  95. package/lib/logic/SolidLogic.js +0 -321
  96. package/lib/logic/SolidLogic.js.map +0 -1
  97. package/lib/profile/ProfileLogic.d.ts +0 -13
  98. package/lib/profile/ProfileLogic.d.ts.map +0 -1
  99. package/lib/profile/ProfileLogic.js.map +0 -1
  100. package/lib/util/UtilityLogic.d.ts +0 -33
  101. package/lib/util/UtilityLogic.d.ts.map +0 -1
  102. package/lib/util/UtilityLogic.js +0 -240
  103. package/lib/util/UtilityLogic.js.map +0 -1
  104. package/lib/util/uri.d.ts +0 -3
  105. package/lib/util/uri.d.ts.map +0 -1
  106. package/lib/util/uri.js +0 -9
  107. package/lib/util/uri.js.map +0 -1
  108. package/src/chat/ChatLogic.ts +0 -244
  109. package/src/chat/determineChatContainer.ts +0 -14
  110. package/src/inbox/InboxLogic.ts +0 -66
  111. package/src/logic/SolidLogic.ts +0 -262
  112. package/src/profile/ProfileLogic.ts +0 -44
  113. package/src/util/UtilityLogic.ts +0 -161
  114. package/src/util/uri.ts +0 -5
@@ -1,117 +1,176 @@
1
- import { NamedNode, st, sym } from "rdflib"
2
- import * as debug from '../util/debug'
3
- import solidNamespace from 'solid-namespace'
4
- import * as $rdf from 'rdflib'
5
- import { newThing } from "../util/uri"
6
- import { AuthenticationContext } from "../types"
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
- * Resolves with the same context, outputting
23
- * output: index.public, index.private
24
- * @@ This is a very bizare function
25
- * @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
26
- */
27
- export async function loadIndex (
28
- context: AuthenticationContext,
29
- isPublic: boolean
30
- ): Promise<AuthenticationContext> {
31
- const indexes = await solidLogicSingleton.loadIndexes(
32
- context.me as NamedNode,
33
- (isPublic ? context.publicProfile || null : null),
34
- (isPublic ? null : context.preferencesFile || null),
35
- // async (err: Error) => widgets.complain(context, err.message)
36
- async (err: Error) => debug.error(err.message) as undefined
37
- )
38
- context.index = context.index || {}
39
- context.index.private = indexes.private.concat(context.index.private || []) // otherwise concat will wrongly add 'undefined' as a private index
40
- context.index.public = indexes.public.concat(context.index.public || []) // otherwise concat will wrongly add 'undefined' as a public index
41
- return context
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
- export async function loadTypeIndexes (context: AuthenticationContext) {
45
- try {
46
- await loadPreferences(solidLogicSingleton.store, context.me as NamedNode)
47
- } catch (error) {
48
- debug.warn(error.message) as undefined
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
- try {
51
- const indexes = await solidLogicSingleton.loadIndexes(
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
- // async (err: Error) => debug.warn(err.message) as undefined
112
+ async (err: Error) => debug.error(err.message) as undefined
57
113
  )
58
114
  context.index = context.index || {}
59
- context.index.private = indexes.private || context.index.private
60
- context.index.public = indexes.public || context.index.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
- * Resolves with the same context, outputting
69
- * @see https://github.com/solidos/solid/blob/main/proposals/data-discovery.md#discoverability
70
- */
71
- export async function ensureTypeIndexes (context: AuthenticationContext, agent?: NamedNode): Promise<AuthenticationContext> {
72
- if (!context.me) {
73
- throw new Error(`ensureTypeIndexes: @@ no user`)
74
- }
75
- await ensureOneTypeIndex(context, true, agent)
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
- * Load or create ONE type index
82
- * Find one or make one or fail
83
- * Many reasons for failing including script not having permission etc
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
- async function putIndex (newIndex) {
95
- try {
96
- await solidLogicSingleton.createEmptyRdfDoc(newIndex, 'Blank initial Type index')
97
- return context
98
- } catch (e) {
99
- const msg = `Error creating new index ${e}`
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
- } // putIndex
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
- debug.log(`Not adding new type index as ${relevant} is not editable`)
112
- return
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 solidLogicSingleton.updatePromise([], addMe)
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
- // officially exists
137
- const ixs = context.index[visibility]
138
- try {
139
- await solidLogicSingleton.load(ixs)
140
- } catch (err) {
141
- const msg = `ensureOneTypeIndex: loading indexes ${err}`
142
- debug.warn(msg)
143
- // widgets.complain(context, `ensureOneTypeIndex: loading indexes ${err}`)
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
- const context2 = await ensureLoadedPreferences(context)
149
- if (!context2.publicProfile) throw new Error(`@@ type index: no publicProfile`)
150
- if (!context2.preferencesFile) throw new Error(`@@ type index: no preferencesFile for profile ${context2.publicProfile}`)
151
- const relevant = isPublic ? context2.publicProfile : context2.preferencesFile
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
- try {
154
- await loadIndex(context2, isPublic)
155
- const pp = isPublic ? 'public' : 'private'
156
- if (context2.index && context2.index[pp]&& context2.index[pp].length > 0) {
157
- debug.log(`ensureOneTypeIndex: Type index exists already ${context2.index[pp]}`)
158
- return context2
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
- await makeIndexIfNecessary(context2, isPublic)
161
- } catch (error) {
162
- await makeIndexIfNecessary(context2, isPublic)
163
- // widgets.complain(context2, 'calling loadIndex:' + error)
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
- * Register a new app in a type index
169
- * used in chat in bookmark.js (solid-ui)
170
- */
171
- export async function registerInTypeIndex (
172
- context: AuthenticationContext,
173
- instance: NamedNode,
174
- theClass: NamedNode,
175
- isPublic: boolean,
176
- agent?: NamedNode // Defaults to current user
177
- ): Promise<AuthenticationContext> {
178
- await ensureOneTypeIndex(context, isPublic, agent)
179
- if (!context.index) {
180
- throw new Error('registerInTypeIndex: No type index found')
181
- }
182
- const indexes = isPublic ? context.index.public : context.index.private
183
- if (!indexes.length) {
184
- throw new Error('registerInTypeIndex: What no type index?')
185
- }
186
- const index = indexes[0]
187
- const registration = newThing(index)
188
- const ins = [
189
- // See https://github.com/solidos/solid/blob/main/proposals/data-discovery.md
190
- st(registration, ns.rdf('type'), ns.solid('TypeRegistration'), index),
191
- st(registration, ns.solid('forClass'), theClass, index),
192
- st(registration, ns.solid('instance'), instance, index)
193
- ]
194
- try {
195
- await solidLogicSingleton.updatePromise([], ins)
196
- } catch (e) {
197
- debug.log(e)
198
- alert(e)
199
- }
200
- return context
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
- interface NewPaneOptions {
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
+