solid-logic 1.3.17-0abe2b84 → 1.3.17-3f057286

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.
@@ -1,59 +1,40 @@
1
- import { NamedNode, Namespace, LiveStore, sym, st } from "rdflib";
2
- // import * as debug from '../util/debug'
3
- // import { getContainerMembers } from '../util/UtilityLogic'
1
+ import { NamedNode, LiveStore, sym, st } from 'rdflib'
2
+ import * as $rdf from 'rdflib'
4
3
  import { solidLogicSingleton } from "../logic/solidLogicSingleton"
5
4
  import { newThing } from "../util/uri"
5
+ import solidNamespace from 'solid-namespace'
6
6
 
7
- const { authn } = solidLogicSingleton
7
+ const { authn } = solidLogicSingleton
8
8
  const { currentUser } = authn
9
+ const ns = solidNamespace($rdf)
9
10
 
10
- type TypeIndexScope = { label: string, index: NamedNode, agent: NamedNode } ;
11
+ type TypeIndexScope = { label: string, index: NamedNode, agent: NamedNode }
11
12
  type ScopedApp = { instance: NamedNode, scope: TypeIndexScope }
12
13
 
13
- const ns = {
14
- dct: Namespace('http://purl.org/dc/terms/'),
15
- ldp: Namespace('http://www.w3.org/ns/ldp#'),
16
- meeting: Namespace('http://www.w3.org/ns/pim/meeting#'),
17
- rdf: Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
18
- schema: Namespace('http://schema.org/'),
19
- solid: Namespace('http://www.w3.org/ns/solid/terms#'),
20
- space: Namespace('http://www.w3.org/ns/pim/space#'),
21
- stat: Namespace('http://www.w3.org/ns/posix/stat#'),
22
- vcard: Namespace('http://www.w3.org/2006/vcard/ns#'),
23
- wf: Namespace('http://www.w3.org/2005/01/wf/flow#'),
24
- xsd: Namespace('http://www.w3.org/2001/XMLSchema#')
25
-
26
- }
27
-
28
- /** Create a resource if it really does not exist
29
- * Be absolutely sure something does not exist before creating a new empty file
14
+ /**
15
+ * Create a resource if it really does not exist
16
+ * Be absolutely sure something does not exist before creating a new empty file
30
17
  * as otherwise existing could be deleted.
31
18
  * @param doc {NamedNode} - The resource
32
19
  */
33
20
  export async function loadOrCreateIfNotExists (store: LiveStore, doc: NamedNode) {
34
21
  let response
35
- // console.log('@@ loadOrCreateIfNotExists doc ', doc)
36
22
  try {
37
23
  response = await store.fetcher.load(doc)
38
24
  } catch (err) {
39
25
  if (err.response.status === 404) {
40
- // console.log('createIfNotExists doc does NOT exist, will create: ' + doc)
41
26
  try {
42
27
  store.fetcher.webOperation('PUT', doc, {data: '', contentType: 'text/turtle'})
43
28
  } catch (err) {
44
29
  const msg = 'createIfNotExists: PUT FAILED: ' + doc + ': ' + err
45
- // console.log(msg)
46
30
  throw new Error(msg)
47
31
  }
48
32
  delete store.fetcher.requested[doc.uri] // delete cached 404 error
49
- // console.log('createIfNotExists doc created ok ' + doc)
50
33
  } else {
51
34
  const msg = 'createIfNotExists doc load error NOT 404: ' + doc + ': ' + err
52
- // console.log(msg)
53
35
  throw new Error(msg) // @@ add nested errors
54
36
  }
55
37
  }
56
- // console.log('createIfNotExists doc exists, all good ' + doc)
57
38
  return response
58
39
  }
59
40
 
@@ -73,20 +54,18 @@ export function suggestPublicTypeIndex (me:NamedNode) {
73
54
  export function suggestPrivateTypeIndex (preferencesFile:NamedNode) {
74
55
  return sym(preferencesFile.doc().dir()?.uri + 'privateTypeIndex.ttl')
75
56
  }
57
+
76
58
  /* Follow link from this doc to another thing, or else make a new link
77
59
  **
78
- ** return: null no ld one and failed to make a new one
60
+ ** return: null no ld one and failed to make a new one
79
61
  */
80
- export async function followOrCreateLink(store: LiveStore, subject: NamedNode, predicate: NamedNode,
62
+ export async function followOrCreateLink (store: LiveStore, subject: NamedNode, predicate: NamedNode,
81
63
  object: NamedNode, doc:NamedNode):Promise<NamedNode | null> {
82
64
  await store.fetcher.load(doc)
83
65
  const result = store.any(subject, predicate, null, doc)
84
- // console.log('@@ followOrCreateLink result ', result)
85
66
 
86
67
  if (result) return result as NamedNode
87
68
  if (!store.updater.editable(doc)) {
88
- // console.log(`followOrCreateLink: Can't modify ${doc} so can't make new link to ${object}.`)
89
- // console.log('followOrCreateLink @@ connectedStatements', store.connectedStatements(subject))
90
69
  return null
91
70
  }
92
71
  try {
@@ -96,58 +75,48 @@ export async function followOrCreateLink(store: LiveStore, subject: NamedNode, p
96
75
  return null
97
76
  }
98
77
 
99
- // console.log(`Success making link in ${doc} to ${object}` )
100
-
101
78
  try {
102
79
  await loadOrCreateIfNotExists(store, object)
103
80
  // store.fetcher.webOperation('PUT', object, { data: '', contentType: 'text/turtle'})
104
81
  } catch (err) {
105
82
  console.warn(`followOrCreateLink: Error loading or saving new linked document: ${object}: ${err}`)
106
83
  }
107
- // console.log(`followOrCreateLink: Success loading or saving new linked document: ${object}.`)
108
84
  return object
109
85
  }
110
86
 
111
- export async function loadProfile(store: LiveStore, user: NamedNode) {
112
- // console.log(' @@ loadProfile: user', user)
87
+ export async function loadProfile (store: LiveStore, user: NamedNode) {
113
88
  if (!user) {
114
89
  throw new Error(`loadProfile: no user given.`)
115
90
  }
116
- // try {
91
+ try {
117
92
  await store.fetcher.load(user.doc())
118
- // } catch (err) {
119
- // throw new Error(`Unable to load profile of user ${user}: ${err}`)
120
- //}
93
+ } catch (err) {
94
+ throw new Error(`Unable to load profile of user ${user}: ${err}`)
95
+ }
121
96
  return user.doc()
122
97
  }
123
98
 
124
- export async function loadPreferences(store: LiveStore, user: NamedNode): Promise <NamedNode | undefined > {
125
- // console.log('loadPreferences @@ user', user)
99
+ export async function loadPreferences (store: LiveStore, user: NamedNode): Promise <NamedNode | undefined > {
126
100
  await loadProfile(store as LiveStore, user)
127
101
 
128
102
  const possiblePreferencesFile = suggestPreferencesFile(user)
129
103
 
130
104
  const preferencesFile = await followOrCreateLink(store, user, ns.space('preferencesFile') as NamedNode, possiblePreferencesFile, user.doc())
131
- // const preferencesFile = store.any(user, ns.space('preferencesFile'), undefined, profile)
132
105
 
133
- // console.log('loadPreferences @@ pref file', preferencesFile)
134
106
  if (!preferencesFile) {
135
107
  const message = `User ${user} has no pointer in profile to preferences file.`
136
108
  console.warn(message)
137
- // throw new Error()
138
109
  return undefined
139
110
  }
140
111
  try {
141
112
  await store.fetcher.load(preferencesFile as NamedNode)
142
- } catch (err) { // Mabeb a permission propblem or origin problem
113
+ } catch (err) { // Maybe a permission propblem or origin problem
143
114
  return undefined
144
- // throw new Error(`Unable to load preferences file ${preferencesFile} of user <${user}>: ${err}`)
145
115
  }
146
116
  return preferencesFile as NamedNode
147
117
  }
148
118
 
149
- export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Promise<Array<TypeIndexScope>> {
150
- // console.log('@@ loadTypeIndexesFor user', user)
119
+ export async function loadTypeIndexesFor (store: LiveStore, user:NamedNode): Promise<Array<TypeIndexScope>> {
151
120
  if (!user) throw new Error(`loadTypeIndexesFor: No user given`)
152
121
  const profile = await loadProfile(store, user)
153
122
 
@@ -155,9 +124,6 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
155
124
 
156
125
  const publicTypeIndex = await followOrCreateLink(store, user, ns.solid('publicTypeIndex') as NamedNode, suggestion, profile)
157
126
 
158
- // const publicTypeIndex = store.any(user, ns.solid('publicTypeIndex'), undefined, profile)
159
- // console.log('@@ loadTypeIndexesFor publicTypeIndex', publicTypeIndex)
160
-
161
127
  const publicScopes = publicTypeIndex ? [ { label: 'public', index: publicTypeIndex as NamedNode, agent: user } ] : []
162
128
 
163
129
  let preferencesFile
@@ -175,7 +141,7 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
175
141
 
176
142
  const privateTypeIndex = store.any(user, ns.solid('privateTypeIndex'), undefined, profile) ||
177
143
 
178
- await followOrCreateLink(store, user, ns.solid('privateTypeIndex') as NamedNode, suggestedPrivateTypeIndex, preferencesFile);
144
+ await followOrCreateLink(store, user, ns.solid('privateTypeIndex') as NamedNode, suggestedPrivateTypeIndex, preferencesFile);
179
145
 
180
146
  privateScopes = privateTypeIndex ? [ { label: 'private', index: privateTypeIndex as NamedNode, agent: user } ] : []
181
147
  } else {
@@ -184,7 +150,6 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
184
150
  const scopes = publicScopes.concat(privateScopes)
185
151
  if (scopes.length === 0) return scopes
186
152
  const files = scopes.map(scope => scope.index)
187
- // console.log('@@ loadTypeIndexesFor files ', files)
188
153
  try {
189
154
  await store.fetcher.load(files)
190
155
  } catch (err) {
@@ -196,14 +161,13 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
196
161
  export async function loadCommunityTypeIndexes (store:LiveStore, user:NamedNode): Promise<TypeIndexScope[][]> {
197
162
  const preferencesFile = await loadPreferences(store, user)
198
163
  if (preferencesFile) { // For now, pick up communities as simple links from the preferences file.
199
- const communities = store.each(user, ns.solid('community'), undefined, preferencesFile as NamedNode)
200
- // console.log('loadCommunityTypeIndexes communities: ',communities)
164
+ const communities = store.each(user, ns.solid('community'), undefined, preferencesFile as NamedNode).concat(
165
+ store.each(user, ns.solid('community'), undefined, user.doc() as NamedNode)
166
+ )
201
167
  let result = []
202
168
  for (const org of communities) {
203
169
  result = result.concat(await loadTypeIndexesFor(store, org as NamedNode) as any)
204
170
  }
205
- // const communityTypeIndexesPromises = communities.map(async community => await loadTypeIndexesFor(store, community as NamedNode))
206
- // const result1 = Promise.all(communityTypeIndexesPromises)
207
171
  return result
208
172
  }
209
173
  return [] // No communities
@@ -214,7 +178,6 @@ export async function loadAllTypeIndexes (store:LiveStore, user:NamedNode) {
214
178
  }
215
179
 
216
180
  // Utility: remove duplicates from Array of NamedNodes
217
-
218
181
  export function uniqueNodes (arr: NamedNode[]): NamedNode[] {
219
182
  const uris = arr.map(x => x.uri)
220
183
  const set = new Set(uris)
@@ -223,53 +186,41 @@ export function uniqueNodes (arr: NamedNode[]): NamedNode[] {
223
186
  return arr2 // Array.from(new Set(arr.map(x => x.uri))).map(u => sym(u))
224
187
  }
225
188
 
226
- export async function getScopedAppsfromIndex (store, scope, theClass: NamedNode) {
227
- // console.log(`getScopedAppsfromIndex agent ${scope.agent} index: ${scope.index}` )
189
+ export async function getScopedAppsFromIndex (store, scope, theClass: NamedNode | null) {
228
190
  const index = scope.index
229
- const registrations = store.each(undefined, ns.solid('forClass'), theClass, index)
230
- // console.log(' registrations', registrations )
231
-
232
- const directInstances = registrations.map(reg => store.each(reg as NamedNode, ns.solid('instance'), null, index)).flat()
233
- // console.log(' directInstances', directInstances )
191
+ const registrations = store.statementsMatching(null, ns.solid('instance'), null, index)
192
+ .concat(store.statementsMatching(null, ns.solid('instanceContainer'), null, index))
193
+ .map(st => st.subject)
194
+ const relevant = theClass ? registrations.filter(reg => store.any(reg, ns.solid('forClass'), null, index).sameTerm(theClass))
195
+ : registrations
196
+ const directInstances = relevant.map(reg => store.each(reg as NamedNode, ns.solid('instance'), null, index)).flat()
234
197
  let instances = uniqueNodes(directInstances)
235
198
 
236
- /*
237
- let instanceContainers = []
238
- for (const reg of registrations) {
239
- const cont = store.any(reg as NamedNode, ns.solid('instanceContainer'), null, index)
240
- if (cont) {
241
- // console.log(' @@ getScopedAppsfromIndex got one: ', cont)
242
- instanceContainers.push(cont)
243
- }
244
- }
245
- */
246
- const instanceContainers = registrations.map(
199
+ const instanceContainers = relevant.map(
247
200
  reg => store.each(reg as NamedNode, ns.solid('instanceContainer'), null, index)).flat()
248
201
 
249
202
  // instanceContainers may be deprocatable if no one has used them
250
-
251
203
  const containers = uniqueNodes(instanceContainers)
204
+ if (containers.length > 0) { console.log('@@ getScopedAppsFromIndex containers ', containers)}
252
205
  for (let i = 0; i < containers.length; i++) {
253
206
  const cont = containers[i]
254
207
  await store.fetcher.load(cont)
255
208
  const contents = store.each(cont, ns.ldp('contains'), null, cont)
256
- // if (contents.length) console.log('getScopedAppsfromIndex @@ instanceContainer contents:', contents)
257
209
  instances = instances.concat(contents)
258
210
  }
259
211
  return instances.map(instance => { return {instance, scope}})
260
212
  }
261
213
 
262
-
263
214
  export async function getScopedAppInstances (store:LiveStore, klass: NamedNode, user: NamedNode):Promise<ScopedApp[]> {
264
- // console.log('getScopedAppInstances @@ ' + user)
265
215
  const scopes = await loadAllTypeIndexes(store, user)
266
216
  let scopedApps = []
267
217
  for (const scope of scopes) {
268
- const scopedApps0 = await getScopedAppsfromIndex(store, scope, klass) as any
218
+ const scopedApps0 = await getScopedAppsFromIndex(store, scope, klass) as any
269
219
  scopedApps = scopedApps.concat(scopedApps0)
270
220
  }
271
221
  return scopedApps
272
222
  }
223
+
273
224
  // This is the function signature which used to be in solid-ui/logic
274
225
  // Recommended to use getScopedAppInstances instead as it provides more information.
275
226
  //
@@ -279,7 +230,8 @@ export async function getAppInstances (store:LiveStore, klass: NamedNode): Promi
279
230
  const scopedAppInstances = await getScopedAppInstances(store, klass, user)
280
231
  return scopedAppInstances.map(scoped => scoped.instance)
281
232
  }
282
- /**
233
+
234
+ /*
283
235
  * Register a new app in a type index
284
236
  * used in chat in bookmark.js (solid-ui)
285
237
  * Returns the registration object if successful else null
@@ -299,7 +251,6 @@ export async function registerInstanceInTypeIndex (
299
251
  st(registration, ns.solid('instance'), instance, index)
300
252
  ]
301
253
  try {
302
- console.log('patching index', ins)
303
254
  await store.updater.update([], ins)
304
255
  } catch (err) {
305
256
  const msg = `Unable to register ${instance} in index ${index}: ${err}`
@@ -308,4 +259,11 @@ export async function registerInstanceInTypeIndex (
308
259
  }
309
260
  return registration
310
261
  }
262
+
263
+ export async function deleteTypeIndexRegistration (store: LiveStore, item) {
264
+ const reg = store.the(null, ns.solid('instance'), item.instance, item.scope.index) as NamedNode
265
+ if (!reg) throw new Error(`deleteTypeIndexRegistration: No registration found for ${item.instance}`)
266
+ const statements = store.statementsMatching(reg, null, null, item.scope.index)
267
+ await store.updater.update(statements, [])
268
+ }
311
269
  // ENDS
package/src/index.ts CHANGED
@@ -20,12 +20,25 @@ export {
20
20
  loadIndex
21
21
  } from './typeIndex/typeIndexLogic'
22
22
 
23
+ // Generate by
24
+ // grep export src/discovery/discoveryLogic.ts | sed -e 's/export //g' | sed -e 's/async //g'| sed -e 's/function //g' | sed -e 's/ .*/,/g' | sort
23
25
  export {
24
- loadProfile,
26
+ deleteTypeIndexRegistration,
27
+ followOrCreateLink,
28
+ getAppInstances,
29
+ getScopedAppInstances,
30
+ getScopedAppsFromIndex,
31
+ loadAllTypeIndexes,
32
+ loadCommunityTypeIndexes,
33
+ loadOrCreateIfNotExists,
25
34
  loadPreferences,
35
+ loadProfile,
26
36
  loadTypeIndexesFor,
27
- loadCommunityTypeIndexes,
28
- loadAllTypeIndexes
37
+ registerInstanceInTypeIndex,
38
+ suggestPreferencesFile,
39
+ suggestPrivateTypeIndex,
40
+ suggestPublicTypeIndex,
41
+ uniqueNodes
29
42
  } from './discovery/discoveryLogic'
30
43
 
31
44
  export { SolidLogic } from './logic/SolidLogic'