solid-logic 1.3.17-8a332867 → 1.3.17-d95df8aa

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