1+ import { NamedNode , LiveStore , sym , st } from 'rdflib'
12import * as $rdf from 'rdflib'
2- import { LiveStore , NamedNode , st , sym } from 'rdflib'
3+ import { solidLogicSingleton } from "../logic/solidLogicSingleton"
4+ import { newThing } from "../util/uri"
35import solidNamespace from 'solid-namespace'
4- import { solidLogicSingleton } from '../logic/solidLogicSingleton'
5- import { newThing } from '../util/uri'
66
77const { authn } = solidLogicSingleton
88const { currentUser } = authn
@@ -18,30 +18,24 @@ type ScopedApp = { instance: NamedNode, scope: TypeIndexScope }
1818 * @param doc {NamedNode} - The resource
1919 */
2020export async function loadOrCreateIfNotExists ( store : LiveStore , doc : NamedNode ) {
21- let response
22- // console.log('@@ loadOrCreateIfNotExists doc ', doc)
23- try {
24- response = await store . fetcher . load ( doc )
25- } catch ( err ) {
26- if ( err . response . status === 404 ) {
27- // console.log('createIfNotExists doc does NOT exist, will create: ' + doc)
28- try {
29- store . fetcher . webOperation ( 'PUT' , doc , { data : '' , contentType : 'text/turtle' } )
30- } catch ( err ) {
31- const msg = 'createIfNotExists: PUT FAILED: ' + doc + ': ' + err
32- // console.log(msg)
33- throw new Error ( msg )
21+ let response
22+ try {
23+ response = await store . fetcher . load ( doc )
24+ } catch ( err ) {
25+ if ( err . response . status === 404 ) {
26+ try {
27+ store . fetcher . webOperation ( 'PUT' , doc , { data : '' , contentType : 'text/turtle' } )
28+ } catch ( err ) {
29+ const msg = 'createIfNotExists: PUT FAILED: ' + doc + ': ' + err
30+ throw new Error ( msg )
31+ }
32+ delete store . fetcher . requested [ doc . uri ] // delete cached 404 error
33+ } else {
34+ const msg = 'createIfNotExists doc load error NOT 404: ' + doc + ': ' + err
35+ throw new Error ( msg ) // @@ add nested errors
3436 }
35- delete store . fetcher . requested [ doc . uri ] // delete cached 404 error
36- // console.log('createIfNotExists doc created ok ' + doc)
37- } else {
38- const msg = 'createIfNotExists doc load error NOT 404: ' + doc + ': ' + err
39- // console.log(msg)
40- throw new Error ( msg ) // @@ add nested errors
41- }
42- }
43- // console.log('createIfNotExists doc exists, all good ' + doc)
44- return response
37+ }
38+ return response
4539}
4640
4741export function suggestPreferencesFile ( me :NamedNode ) {
@@ -65,16 +59,13 @@ export function suggestPrivateTypeIndex (preferencesFile:NamedNode) {
6559**
6660** return: null no ld one and failed to make a new one
6761*/
68- export async function followOrCreateLink ( store : LiveStore , subject : NamedNode , predicate : NamedNode ,
69- object : NamedNode , doc :NamedNode ) :Promise < NamedNode | null > {
62+ export async function followOrCreateLink ( store : LiveStore , subject : NamedNode , predicate : NamedNode ,
63+ object : NamedNode , doc :NamedNode ) :Promise < NamedNode | null > {
7064 await store . fetcher . load ( doc )
7165 const result = store . any ( subject , predicate , null , doc )
72- // console.log('@@ followOrCreateLink result ', result)
7366
7467 if ( result ) return result as NamedNode
7568 if ( ! store . updater . editable ( doc ) ) {
76- // console.log(`followOrCreateLink: Can't modify ${doc} so can't make new link to ${object}.`)
77- // console.log('followOrCreateLink @@ connectedStatements', store.connectedStatements(subject))
7869 return null
7970 }
8071 try {
@@ -84,67 +75,55 @@ export async function followOrCreateLink(store: LiveStore, subject: NamedNode, p
8475 return null
8576 }
8677
87- // console.log(`Success making link in ${doc} to ${object}` )
88-
8978 try {
9079 await loadOrCreateIfNotExists ( store , object )
9180 // store.fetcher.webOperation('PUT', object, { data: '', contentType: 'text/turtle'})
9281 } catch ( err ) {
9382 console . warn ( `followOrCreateLink: Error loading or saving new linked document: ${ object } : ${ err } ` )
9483 }
95- // console.log(`followOrCreateLink: Success loading or saving new linked document: ${object}.`)
9684 return object
9785}
9886
99- export async function loadProfile ( store : LiveStore , user : NamedNode ) {
100- // console.log(' @@ loadProfile: user', user)
87+ export async function loadProfile ( store : LiveStore , user : NamedNode ) {
10188 if ( ! user ) {
10289 throw new Error ( `loadProfile: no user given.` )
10390 }
104- // try {
91+ try {
10592 await store . fetcher . load ( user . doc ( ) )
106- // } catch (err) {
107- // throw new Error(`Unable to load profile of user ${user}: ${err}`)
108- // }
93+ } catch ( err ) {
94+ throw new Error ( `Unable to load profile of user ${ user } : ${ err } ` )
95+ }
10996 return user . doc ( )
11097}
11198
112- export async function loadPreferences ( store : LiveStore , user : NamedNode ) : Promise < NamedNode | undefined > {
113- // console.log('loadPreferences @@ user', user)
99+ export async function loadPreferences ( store : LiveStore , user : NamedNode ) : Promise < NamedNode | undefined > {
114100 await loadProfile ( store as LiveStore , user )
115101
116102 const possiblePreferencesFile = suggestPreferencesFile ( user )
117103
118104 const preferencesFile = await followOrCreateLink ( store , user , ns . space ( 'preferencesFile' ) as NamedNode , possiblePreferencesFile , user . doc ( ) )
119105
120- // console.log('loadPreferences @@ pref file', preferencesFile)
121106 if ( ! preferencesFile ) {
122107 const message = `User ${ user } has no pointer in profile to preferences file.`
123108 console . warn ( message )
124- // throw new Error()
125109 return undefined
126110 }
127111 try {
128112 await store . fetcher . load ( preferencesFile as NamedNode )
129113 } catch ( err ) { // Maybe a permission propblem or origin problem
130114 return undefined
131- // throw new Error(`Unable to load preferences file ${preferencesFile} of user <${user}>: ${err}`)
132115 }
133116 return preferencesFile as NamedNode
134117}
135118
136- export async function loadTypeIndexesFor ( store : LiveStore , user :NamedNode ) : Promise < Array < TypeIndexScope > > {
137- // console.log('@@ loadTypeIndexesFor user', user)
119+ export async function loadTypeIndexesFor ( store : LiveStore , user :NamedNode ) : Promise < Array < TypeIndexScope > > {
138120 if ( ! user ) throw new Error ( `loadTypeIndexesFor: No user given` )
139121 const profile = await loadProfile ( store , user )
140122
141123 const suggestion = suggestPublicTypeIndex ( user )
142124
143125 const publicTypeIndex = await followOrCreateLink ( store , user , ns . solid ( 'publicTypeIndex' ) as NamedNode , suggestion , profile )
144126
145- // const publicTypeIndex = store.any(user, ns.solid('publicTypeIndex'), undefined, profile)
146- // console.log('@@ loadTypeIndexesFor publicTypeIndex', publicTypeIndex)
147-
148127 const publicScopes = publicTypeIndex ? [ { label : 'public' , index : publicTypeIndex as NamedNode , agent : user } ] : [ ]
149128
150129 let preferencesFile
@@ -171,7 +150,6 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
171150 const scopes = publicScopes . concat ( privateScopes )
172151 if ( scopes . length === 0 ) return scopes
173152 const files = scopes . map ( scope => scope . index )
174- // console.log('@@ loadTypeIndexesFor files ', files)
175153 try {
176154 await store . fetcher . load ( files )
177155 } catch ( err ) {
@@ -183,14 +161,13 @@ export async function loadTypeIndexesFor(store: LiveStore, user:NamedNode): Prom
183161export async function loadCommunityTypeIndexes ( store :LiveStore , user :NamedNode ) : Promise < TypeIndexScope [ ] [ ] > {
184162 const preferencesFile = await loadPreferences ( store , user )
185163 if ( preferencesFile ) { // For now, pick up communities as simple links from the preferences file.
186- const communities = store . each ( user , ns . solid ( 'community' ) , undefined , preferencesFile as NamedNode )
187- // 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+ )
188167 let result = [ ]
189168 for ( const org of communities ) {
190169 result = result . concat ( await loadTypeIndexesFor ( store , org as NamedNode ) as any )
191170 }
192- // const communityTypeIndexesPromises = communities.map(async community => await loadTypeIndexesFor(store, community as NamedNode))
193- // const result1 = Promise.all(communityTypeIndexesPromises)
194171 return result
195172 }
196173 return [ ] // No communities
@@ -209,38 +186,36 @@ export function uniqueNodes (arr: NamedNode[]): NamedNode[] {
209186 return arr2 // Array.from(new Set(arr.map(x => x.uri))).map(u => sym(u))
210187}
211188
212- export async function getScopedAppsfromIndex ( store , scope , theClass : NamedNode ) {
213- // console.log(`getScopedAppsfromIndex agent ${scope.agent} index: ${scope.index}` )
189+ export async function getScopedAppsFromIndex ( store , scope , theClass : NamedNode | null ) {
214190 const index = scope . index
215- const registrations = store . each ( undefined , ns . solid ( 'forClass' ) , theClass , index )
216- // console.log(' registrations', registrations )
217-
218- const directInstances = registrations . map ( reg => store . each ( reg as NamedNode , ns . solid ( 'instance' ) , null , index ) ) . flat ( )
219- // 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 ( )
220197 let instances = uniqueNodes ( directInstances )
221198
222- const instanceContainers = registrations . map (
223- reg => store . each ( reg as NamedNode , ns . solid ( 'instanceContainer' ) , null , index )
224- ) . flat ( )
199+ const instanceContainers = relevant . map (
200+ reg => store . each ( reg as NamedNode , ns . solid ( 'instanceContainer' ) , null , index ) ) . flat ( )
225201
226202 // instanceContainers may be deprocatable if no one has used them
227203 const containers = uniqueNodes ( instanceContainers )
204+ if ( containers . length > 0 ) { console . log ( '@@ getScopedAppsFromIndex containers ' , containers ) }
228205 for ( let i = 0 ; i < containers . length ; i ++ ) {
229206 const cont = containers [ i ]
230207 await store . fetcher . load ( cont )
231208 const contents = store . each ( cont , ns . ldp ( 'contains' ) , null , cont )
232- // if (contents.length) console.log('getScopedAppsfromIndex @@ instanceContainer contents:', contents)
233209 instances = instances . concat ( contents )
234210 }
235211 return instances . map ( instance => { return { instance, scope} } )
236212}
237213
238214export async function getScopedAppInstances ( store :LiveStore , klass : NamedNode , user : NamedNode ) :Promise < ScopedApp [ ] > {
239- // console.log('getScopedAppInstances @@ ' + user)
240215 const scopes = await loadAllTypeIndexes ( store , user )
241216 let scopedApps = [ ]
242217 for ( const scope of scopes ) {
243- const scopedApps0 = await getScopedAppsfromIndex ( store , scope , klass ) as any
218+ const scopedApps0 = await getScopedAppsFromIndex ( store , scope , klass ) as any
244219 scopedApps = scopedApps . concat ( scopedApps0 )
245220 }
246221 return scopedApps
@@ -268,21 +243,27 @@ export async function registerInstanceInTypeIndex (
268243 theClass : NamedNode ,
269244 // agent: NamedNode
270245) : Promise < NamedNode | null > {
271- const registration = newThing ( index )
272- const ins = [
273- // See https://github.com/solid/solid/blob/main/proposals/data-discovery.md
274- st ( registration , ns . rdf ( 'type' ) , ns . solid ( 'TypeRegistration' ) , index ) ,
275- st ( registration , ns . solid ( 'forClass' ) , theClass , index ) ,
276- st ( registration , ns . solid ( 'instance' ) , instance , index )
277- ]
278- try {
279- console . log ( 'patching index' , ins )
280- await store . updater . update ( [ ] , ins )
281- } catch ( err ) {
282- const msg = `Unable to register ${ instance } in index ${ index } : ${ err } `
283- console . warn ( msg )
284- return null
285- }
286- return registration
246+ const registration = newThing ( index )
247+ const ins = [
248+ // See https://github.com/solid/solid/blob/main/proposals/data-discovery.md
249+ st ( registration , ns . rdf ( 'type' ) , ns . solid ( 'TypeRegistration' ) , index ) ,
250+ st ( registration , ns . solid ( 'forClass' ) , theClass , index ) ,
251+ st ( registration , ns . solid ( 'instance' ) , instance , index )
252+ ]
253+ try {
254+ await store . updater . update ( [ ] , ins )
255+ } catch ( err ) {
256+ const msg = `Unable to register ${ instance } in index ${ index } : ${ err } `
257+ console . warn ( msg )
258+ return null
259+ }
260+ return registration
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 , [ ] )
287268}
288269// ENDS
0 commit comments