solid-logic 1.3.14-85e374e6 → 1.3.14-893f00f6

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 (40) hide show
  1. package/lib/acl/aclLogic.js +5 -1
  2. package/lib/acl/aclLogic.js.map +1 -1
  3. package/lib/authn/SolidAuthnLogic.js +5 -1
  4. package/lib/authn/SolidAuthnLogic.js.map +1 -1
  5. package/lib/authn/authUtil.js +5 -1
  6. package/lib/authn/authUtil.js.map +1 -1
  7. package/lib/discovery/discoveryLogic.d.ts +13 -0
  8. package/lib/discovery/discoveryLogic.d.ts.map +1 -0
  9. package/lib/discovery/discoveryLogic.js +203 -0
  10. package/lib/discovery/discoveryLogic.js.map +1 -0
  11. package/lib/inbox/InboxLogic.js +2 -2
  12. package/lib/inbox/InboxLogic.js.map +1 -1
  13. package/lib/index.d.ts +1 -0
  14. package/lib/index.d.ts.map +1 -1
  15. package/lib/index.js +7 -1
  16. package/lib/index.js.map +1 -1
  17. package/lib/logic/SolidLogic.d.ts +1 -2
  18. package/lib/logic/SolidLogic.d.ts.map +1 -1
  19. package/lib/logic/SolidLogic.js +43 -40
  20. package/lib/logic/SolidLogic.js.map +1 -1
  21. package/lib/logic/solidLogicSingleton.js +5 -1
  22. package/lib/logic/solidLogicSingleton.js.map +1 -1
  23. package/lib/typeIndex/typeIndexLogic.d.ts +4 -4
  24. package/lib/typeIndex/typeIndexLogic.d.ts.map +1 -1
  25. package/lib/typeIndex/typeIndexLogic.js +98 -32
  26. package/lib/typeIndex/typeIndexLogic.js.map +1 -1
  27. package/lib/util/UtilityLogic.d.ts +2 -2
  28. package/lib/util/UtilityLogic.d.ts.map +1 -1
  29. package/lib/util/UtilityLogic.js +6 -6
  30. package/lib/util/UtilityLogic.js.map +1 -1
  31. package/package.json +12 -15
  32. package/src/discovery/discoveryLogic.ts +90 -0
  33. package/src/inbox/InboxLogic.ts +2 -2
  34. package/src/index.ts +10 -0
  35. package/src/logic/SolidLogic.ts +28 -31
  36. package/src/typeIndex/typeIndexLogic.ts +92 -61
  37. package/src/util/UtilityLogic.ts +8 -8
  38. package/test/chatLogic.test.ts +1 -1
  39. package/test/typeIndexLogic.test.ts +4 -3
  40. package/renovate.json +0 -5
@@ -9,7 +9,12 @@ import { AuthnLogic, SolidNamespace } from "../types";
9
9
  import * as debug from "../util/debug";
10
10
  import { UtilityLogic } from "../util/UtilityLogic";
11
11
  import { CrossOriginForbiddenError, FetchError, NotFoundError, SameOriginForbiddenError, UnauthorizedError } from "./CustomError";
12
-
12
+ /*
13
+ ** It is important to distinquish `fetch`, a function provided by the browser
14
+ ** and `Fetcher`, a helper object for the rdflib Store which turns it
15
+ ** into a `ConnectedStore` or a `LiveStore`. A Fetcher object is
16
+ ** available at store.fetcher, and `fetch` function at `store.fetcher._fetch`,
17
+ */
13
18
 
14
19
  const ns: SolidNamespace = solidNamespace(rdf);
15
20
 
@@ -25,7 +30,7 @@ export class SolidLogic {
25
30
 
26
31
  store: LiveStore;
27
32
  me: string | undefined;
28
- fetcher: { fetch: (url: string, options?: any) => any };
33
+ underlyingFetch: { fetch: (url: string, options?: any) => any };
29
34
 
30
35
  chat: ChatLogic;
31
36
  profile: ProfileLogic;
@@ -33,52 +38,56 @@ export class SolidLogic {
33
38
  util: UtilityLogic;
34
39
 
35
40
  constructor(fetcher: { fetch: (url: any, requestInit: any) => any }, session: Session) {
41
+ // would xpect to be able to do it this way: but get TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation status: 999
42
+ // this.store = new rdf.LiveStore({})
43
+ // this.store.fetcher._fetch = fetch
44
+
36
45
  this.store = rdf.graph() as LiveStore; // Make a Quad store
37
- rdf.fetcher(this.store, fetcher); // Attach a web I/O module, store.fetcher
46
+ rdf.fetcher(this.store, fetch); // Attach a web I/O module, store.fetcher
38
47
  this.store.updater = new rdf.UpdateManager(this.store); // Add real-time live updates store.updater
48
+
39
49
  this.store.features = [] // disable automatic node merging on store load
40
50
  this.cache = {
41
51
  profileDocument: {},
42
52
  preferencesFile: {},
43
53
  };
44
- this.fetcher = fetcher;
54
+ this.underlyingFetch = { fetch: fetch };
45
55
  this.authn = new SolidAuthnLogic(session);
46
56
  debug.log('SolidAuthnLogic initialized')
47
57
  this.profile = new ProfileLogic(this.store, ns, this.authn);
48
58
  this.chat = new ChatLogic(this.store, ns, this.profile);
49
- this.util = new UtilityLogic(this.store, ns, this.fetcher);
59
+ this.util = new UtilityLogic(this.store, ns, this.underlyingFetch);
50
60
  }
51
61
 
52
62
  findAclDocUrl(url: string) {
53
63
  return this.util.findAclDocUrl(url);
54
64
  }
55
65
 
56
- loadDoc(doc: NamedNode): Promise<void> {
57
- return this.util.loadDoc(doc);
58
- }
59
-
60
66
  async loadProfile(me: NamedNode): Promise<NamedNode> {
61
- // console.log('loadProfile', me)
67
+ /*
68
+ // console.log('loadProfile cache ', this.cache)
62
69
  if (this.cache.profileDocument[me.value]) {
63
70
  return this.cache.profileDocument[me.value];
64
- }
65
- let profileDocument;
71
+ } @@ just use the cache in the store
72
+ */
73
+ console.log('loadProfile me ', me)
74
+ const profileDocument = me.doc()
66
75
  try {
67
- profileDocument = me.doc();
68
- await this.loadDoc(profileDocument);
69
- return profileDocument;
76
+ await this.store.fetcher.load(profileDocument);
77
+ return profileDocument;
70
78
  } catch (err) {
71
- const message = `Logged in but cannot load profile ${profileDocument} : ${err}`;
79
+ const message = `Cannot load profile ${profileDocument} : ${err}`;
72
80
  throw new Error(message);
73
81
  }
74
82
  }
75
83
 
76
84
  async loadPreferences(me: NamedNode): Promise<NamedNode> {
77
- // console.log('loadPreferences', me)
85
+ console.log('loadPreferences cache ', this.cache)
78
86
  if (this.cache.preferencesFile[me.value]) {
79
87
  return this.cache.preferencesFile[me.value];
80
88
  }
81
- const preferencesFile = this.store.any(me, ns.space("preferencesFile"));
89
+ await this.loadProfile(me) // Load pointer to pref file
90
+ const preferencesFile = this.store.any(me, ns.space('preferencesFile'), null, me.doc());
82
91
 
83
92
  // console.log('this.store.any()', this.store.any())
84
93
  /**
@@ -100,9 +109,6 @@ export class SolidLogic {
100
109
  );
101
110
  }
102
111
 
103
- if (!this.store.fetcher) {
104
- throw new Error("Cannot load doc, have no fetcher");
105
- }
106
112
  // //// Load preference file
107
113
  try {
108
114
  await this.store.fetcher.load(preferencesFile as NamedNode, {
@@ -152,9 +158,6 @@ export class SolidLogic {
152
158
  }
153
159
 
154
160
  load(doc: NamedNode | NamedNode[] | string) {
155
- if (!this.store.fetcher) {
156
- throw new Error("Cannot load doc(s), have no fetcher");
157
- }
158
161
  return this.store.fetcher.load(doc);
159
162
  }
160
163
 
@@ -210,9 +213,6 @@ export class SolidLogic {
210
213
  }
211
214
 
212
215
  async createEmptyRdfDoc(doc: NamedNode, comment: string) {
213
- if (!this.store.fetcher) {
214
- throw new Error("Cannot create empty rdf doc, have no fetcher");
215
- }
216
216
  await this.store.fetcher.webOperation("PUT", doc.uri, {
217
217
  data: `# ${new Date()} ${comment}
218
218
  `,
@@ -226,9 +226,6 @@ export class SolidLogic {
226
226
  ins: Array<Statement> = []
227
227
  ): Promise<void> {
228
228
  return new Promise((resolve, reject) => {
229
- if (!this.store.updater) {
230
- throw new Error("Cannot updatePromise, have no updater");
231
- }
232
229
  this.store.updater.update(del, ins, function (_uri, ok, errorBody) {
233
230
  if (!ok) {
234
231
  reject(new Error(errorBody));
@@ -260,6 +257,6 @@ export class SolidLogic {
260
257
  }
261
258
 
262
259
  async fetch(url: string, options?: any) {
263
- return this.fetcher.fetch(url, options);
260
+ return this.underlyingFetch.fetch(url, options);
264
261
  }
265
262
  }
@@ -5,13 +5,23 @@ import * as $rdf from 'rdflib'
5
5
  import { newThing } from "../util/uri"
6
6
  import { AuthenticationContext } from "../types"
7
7
  import { solidLogicSingleton } from "../logic/solidLogicSingleton"
8
-
8
+ // import { ensureLoadedPreferences } from '../logic/logic'
9
+ import { loadPreferences, loadProfile } from '../discovery/discoveryLogic'
9
10
  export const ns = solidNamespace($rdf)
10
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
+ }
20
+
11
21
  /**
12
22
  * Resolves with the same context, outputting
13
23
  * output: index.public, index.private
14
- *
24
+ * @@ This is a very bizare function
15
25
  * @see https://github.com/solid/solid/blob/main/proposals/data-discovery.md#discoverability
16
26
  */
17
27
  export async function loadIndex (
@@ -26,32 +36,44 @@ const indexes = await solidLogicSingleton.loadIndexes(
26
36
  async (err: Error) => debug.error(err.message) as undefined
27
37
  )
28
38
  context.index = context.index || {}
29
- context.index.private = indexes.private || context.index.private
30
- context.index.public = indexes.public || context.index.public
39
+ context.index.private = indexes.private.concat(context.index.private)
40
+ context.index.public = indexes.public.concat(context.index.public)
31
41
  return context
32
42
  }
33
43
 
34
44
  export async function loadTypeIndexes (context: AuthenticationContext) {
35
- const indexes = await solidLogicSingleton.loadIndexes(
36
- context.me as NamedNode,
37
- context.publicProfile || null,
38
- context.preferencesFile || null,
39
- // async (err: Error) => widgets.complain(context, err.message)
40
- async (err: Error) => debug.warn(err.message) as undefined
41
- )
42
- context.index = context.index || {}
43
- context.index.private = indexes.private || context.index.private
44
- context.index.public = indexes.public || context.index.public
45
- return context
45
+ try {
46
+ await loadPreferences(solidLogicSingleton.store, context.me)
47
+ } catch (error) {
48
+ debug.warn(error.message) as undefined
49
+ }
50
+ try {
51
+ const indexes = await solidLogicSingleton.loadIndexes(
52
+ context.me as NamedNode,
53
+ context.publicProfile || null,
54
+ context.preferencesFile || null,
55
+ // async (err: Error) => widgets.complain(context, err.message)
56
+ // async (err: Error) => debug.warn(err.message) as undefined
57
+ )
58
+ context.index = context.index || {}
59
+ context.index.private = indexes.private || context.index.private
60
+ context.index.public = indexes.public || context.index.public
61
+ return context
62
+ } catch (error) {
63
+ async (error: Error) => debug.warn(error.message) as undefined
64
+ }
46
65
  }
47
66
 
48
67
  /**
49
68
  * Resolves with the same context, outputting
50
69
  * @see https://github.com/solid/solid/blob/main/proposals/data-discovery.md#discoverability
51
70
  */
52
- export async function ensureTypeIndexes (context: AuthenticationContext): Promise<AuthenticationContext> {
53
- await ensureOneTypeIndex(context, true)
54
- await ensureOneTypeIndex(context, false)
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)
55
77
  return context
56
78
  }
57
79
 
@@ -63,9 +85,10 @@ return context
63
85
  * Adds its output to the context
64
86
  * @see https://github.com/solid/solid/blob/main/proposals/data-discovery.md#discoverability
65
87
  */
66
- async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boolean): Promise<AuthenticationContext | void> {
88
+ async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boolean, agent?: NamedNode): Promise<AuthenticationContext | void> {
67
89
  async function makeIndexIfNecessary (context, isPublic) {
68
90
  const relevant = isPublic ? context.publicProfile : context.preferencesFile
91
+ if (!relevant) alert ('@@@@ relevent null')
69
92
  const visibility = isPublic ? 'public' : 'private'
70
93
 
71
94
  async function putIndex (newIndex) {
@@ -79,58 +102,65 @@ async function ensureOneTypeIndex (context: AuthenticationContext, isPublic: boo
79
102
  }
80
103
  } // putIndex
81
104
 
105
+
82
106
  context.index = context.index || {}
83
107
  context.index[visibility] = context.index[visibility] || []
84
108
  let newIndex
85
109
  if (context.index[visibility].length === 0) {
86
- newIndex = sym(`${relevant.dir().uri + visibility}TypeIndex.ttl`)
87
- debug.log(`Linking to new fresh type index ${newIndex}`)
88
- if (!confirm(`OK to create a new empty index file at ${newIndex}, overwriting anything that is now there?`)) {
89
- throw new Error('cancelled by user')
90
- }
91
- debug.log(`Linking to new fresh type index ${newIndex}`)
92
- const addMe = [
93
- st(context.me, ns.solid(`${visibility}TypeIndex`), newIndex, relevant)
94
- ]
95
- try {
96
- await solidLogicSingleton.updatePromise([], addMe)
97
- } catch (err) {
98
- const msg = `Error saving type index link saving back ${newIndex}: ${err}`
99
- //widgets.complain(context, msg)
100
- debug.warn(msg)
101
- return context
102
- }
110
+ if (!store.updater.editable(relevant)) {
111
+ debug.log(`Not adding new type index as ${relevant} is not editable`)
112
+ return
113
+ }
114
+ newIndex = sym(`${relevant.dir().uri + visibility}TypeIndex.ttl`)
115
+ debug.log(`Linking to new fresh type index ${newIndex}`)
116
+ if (!confirm(`OK to create a new empty index file at ${newIndex}, overwriting anything that is now there?`)) {
117
+ throw new Error('cancelled by user')
118
+ }
119
+ debug.log(`Linking to new fresh type index ${newIndex}`)
120
+ const addMe = [
121
+ st(context.me, ns.solid(`${visibility}TypeIndex`), newIndex, relevant)
122
+ ]
123
+ try {
124
+ await solidLogicSingleton.updatePromise([], addMe)
125
+ } catch (err) {
126
+ const msg = `Error saving type index link saving back ${newIndex}: ${err}`
127
+ //widgets.complain(context, msg)
128
+ debug.warn(msg)
129
+ return context
130
+ }
103
131
 
104
- debug.log(`Creating new fresh type index file${newIndex}`)
105
- await putIndex(newIndex)
106
- context.index[visibility].push(newIndex) // @@ wait
132
+ debug.log(`Creating new fresh type index file${newIndex}`)
133
+ await putIndex(newIndex)
134
+ context.index[visibility].push(newIndex) // @@ wait
107
135
  } else {
108
136
  // officially exists
109
- const ixs = context.index[visibility]
110
- try {
111
- await solidLogicSingleton.load(ixs)
112
- } catch (err) {
113
- const msg = `ensureOneTypeIndex: loading indexes ${err}`
114
- debug.warn(msg)
115
- // widgets.complain(context, `ensureOneTypeIndex: loading indexes ${err}`)
116
- }
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
+ }
117
145
  }
118
146
  } // makeIndexIfNecessary
119
147
 
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
152
+
120
153
  try {
121
- await loadIndex(context, isPublic)
122
- if (context.index) {
123
- debug.log(
124
- `ensureOneTypeIndex: Type index exists already ${isPublic
125
- ? context.index.public[0]
126
- : context.index.private[0]
127
- }`
128
- )
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
129
159
  }
130
- return context
160
+ await makeIndexIfNecessary(context2, isPublic)
131
161
  } catch (error) {
132
- await makeIndexIfNecessary(context, isPublic)
133
- // widgets.complain(context, 'calling loadIndex:' + error)
162
+ await makeIndexIfNecessary(context2, isPublic)
163
+ // widgets.complain(context2, 'calling loadIndex:' + error)
134
164
  }
135
165
  }
136
166
 
@@ -142,9 +172,10 @@ export async function registerInTypeIndex (
142
172
  context: AuthenticationContext,
143
173
  instance: NamedNode,
144
174
  theClass: NamedNode,
145
- isPublic: boolean
175
+ isPublic: boolean,
176
+ agent?: NamedNode // Defaults to current user
146
177
  ): Promise<AuthenticationContext> {
147
- await ensureOneTypeIndex(context, isPublic)
178
+ await ensureOneTypeIndex(context, isPublic, agent)
148
179
  if (!context.index) {
149
180
  throw new Error('registerInTypeIndex: No type index found')
150
181
  }
@@ -167,4 +198,4 @@ isPublic: boolean
167
198
  alert(e)
168
199
  }
169
200
  return context
170
- }
201
+ }
@@ -11,12 +11,12 @@ export const ACL_LINK = sym(
11
11
  export class UtilityLogic {
12
12
  store: LiveStore;
13
13
  ns: SolidNamespace;
14
- fetcher: { fetch: (url: string, options?: any) => any };
14
+ underlyingFetch: { fetch: (url: string, options?: any) => any };
15
15
 
16
- constructor(store: LiveStore, ns: SolidNamespace, fetcher: { fetch: (url: string, options?: any) => any }) {
16
+ constructor(store: LiveStore, ns: SolidNamespace, underlyingFetch: { fetch: (url: string, options?: any) => any }) {
17
17
  this.store = store;
18
18
  this.ns = ns;
19
- this.fetcher = fetcher;
19
+ this.underlyingFetch = underlyingFetch;
20
20
  }
21
21
 
22
22
  async findAclDocUrl(url: string) {
@@ -65,7 +65,7 @@ export class UtilityLogic {
65
65
  ].join('\n')
66
66
  }
67
67
  const aclDocUrl = await this.findAclDocUrl(options.target);
68
- return this.fetcher.fetch(aclDocUrl, {
68
+ return this.underlyingFetch.fetch(aclDocUrl, {
69
69
  method: 'PUT',
70
70
  body: str,
71
71
  headers: [
@@ -83,7 +83,7 @@ export class UtilityLogic {
83
83
  throw new Error("Cannot load doc, have no fetcher");
84
84
  }
85
85
  await this.store.fetcher.load(doc, {
86
- withCredentials: false,
86
+ withCredentials: false, // @@ BUT this won't work when logged in an accessing private stuff!
87
87
  cache: "reload",
88
88
  });
89
89
  // console.log('loaded', profileDocument, this.store)
@@ -98,7 +98,7 @@ export class UtilityLogic {
98
98
  throw new Error(`Not a container URL ${url}`);
99
99
  }
100
100
  // Copied from https://github.com/solid/solid-crud-tests/blob/v3.1.0/test/surface/create-container.test.ts#L56-L64
101
- const result = await this.fetcher.fetch(url, {
101
+ const result = await this.underlyingFetch.fetch(url, {
102
102
  method: "PUT",
103
103
  headers: {
104
104
  "Content-Type": "text/turtle",
@@ -134,13 +134,13 @@ export class UtilityLogic {
134
134
  try {
135
135
  if (this.isContainer(url)) {
136
136
  const aclDocUrl = await this.findAclDocUrl(url);
137
- await this.fetcher.fetch(aclDocUrl, { method: "DELETE" });
137
+ await this.underlyingFetch.fetch(aclDocUrl, { method: "DELETE" });
138
138
  const containerMembers = await this.getContainerMembers(url);
139
139
  await Promise.all(
140
140
  containerMembers.map((url) => this.recursiveDelete(url))
141
141
  );
142
142
  }
143
- return this.fetcher.fetch(url, { method: "DELETE" });
143
+ return this.underlyingFetch.fetch(url, { method: "DELETE" });
144
144
  } catch (e) {
145
145
  // console.log(`Please manually remove ${url} from your system under test.`, e);
146
146
  }
@@ -20,7 +20,7 @@ describe("Chat logic", () => {
20
20
  status: 404,
21
21
  });
22
22
  store = rdf.graph();
23
- store.fetcher = rdf.fetcher(store, { fetch: fetchMock });
23
+ store.fetcher = rdf.fetcher(store, { fetch: fetchMock, timeout: 5 });
24
24
  store.updater = new UpdateManager(store);
25
25
  const authn = {
26
26
  currentUser: () => {
@@ -15,12 +15,13 @@ describe('registerInTypeIndex', () => {
15
15
  it('exists', () => {
16
16
  expect(typeIndexLogic.registerInTypeIndex).toBeInstanceOf(Function)
17
17
  })
18
- it.skip('runs', async () => {
19
- expect(await typeIndexLogic.registerInTypeIndex(
18
+ it('throws error', async () => {
19
+ expect(typeIndexLogic.registerInTypeIndex(
20
20
  {} as AuthenticationContext,
21
21
  sym('https://test.test#'),
22
22
  sym('https://test.test#'),
23
23
  false
24
- )).toEqual(undefined)
24
+ )).rejects
25
+ .toThrow('@@ ensureLoadedPreferences: no user specified')
25
26
  })
26
27
  })
package/renovate.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "extends": [
3
- "config:base"
4
- ]
5
- }