@noeldemartin/solid-utils 0.4.0-next.c9d36a1c12735b50a915e6ffeed60e60569706c0 → 0.5.0-next.1ea2ba307e0da5c3ce9d2db1276f930c7aa52c90

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noeldemartin/solid-utils",
3
- "version": "0.4.0-next.c9d36a1c12735b50a915e6ffeed60e60569706c0",
3
+ "version": "0.5.0-next.1ea2ba307e0da5c3ce9d2db1276f930c7aa52c90",
4
4
  "description": "My JavaScript utilities for Solid",
5
5
  "main": "dist/noeldemartin-solid-utils.cjs.js",
6
6
  "module": "dist/noeldemartin-solid-utils.esm.js",
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "@babel/runtime": "^7.14.0",
34
34
  "@noeldemartin/solid-utils-external": "^0.1.1",
35
- "@noeldemartin/utils": "^0.5.1",
35
+ "@noeldemartin/utils": "^0.6.0",
36
36
  "@rdfjs/types": "^1.1.0",
37
37
  "core-js": "^3.12.1",
38
38
  "md5": "^2.3.0"
@@ -5,7 +5,7 @@ import UnauthorizedError from '../errors/UnauthorizedError';
5
5
  import type SolidDocument from '../models/SolidDocument';
6
6
 
7
7
  import { fetchSolidDocument } from './io';
8
- import type { Fetch } from './io';
8
+ import type { Fetch, FetchSolidDocumentOptions } from './io';
9
9
 
10
10
  export interface SolidUserProfile {
11
11
  webId: string;
@@ -19,7 +19,7 @@ export interface SolidUserProfile {
19
19
  privateTypeIndexUrl?: string;
20
20
  }
21
21
 
22
- async function fetchExtendedUserProfile(webIdDocument: SolidDocument, fetch?: Fetch): Promise<{
22
+ async function fetchExtendedUserProfile(webIdDocument: SolidDocument, options?: FetchSolidDocumentOptions): Promise<{
23
23
  store: SolidStore;
24
24
  cloaked: boolean;
25
25
  writableProfileUrl: string | null;
@@ -43,7 +43,7 @@ async function fetchExtendedUserProfile(webIdDocument: SolidDocument, fetch?: Fe
43
43
  }
44
44
 
45
45
  try {
46
- const document = await fetchSolidDocument(url, fetch);
46
+ const document = await fetchSolidDocument(url, options);
47
47
 
48
48
  documents[url] = document;
49
49
  store.addQuads(document.getQuads());
@@ -81,21 +81,29 @@ async function fetchExtendedUserProfile(webIdDocument: SolidDocument, fetch?: Fe
81
81
  }
82
82
 
83
83
  async function fetchUserProfile(webId: string, options: FetchUserProfileOptions = {}): Promise<SolidUserProfile> {
84
+ const requestOptions: FetchSolidDocumentOptions = {
85
+ fetch: options.fetch,
86
+
87
+ // Needed for CSS v7.1.3.
88
+ // See https://github.com/CommunitySolidServer/CommunitySolidServer/issues/1972
89
+ cache: 'no-store',
90
+ };
91
+
84
92
  const documentUrl = urlRoute(webId);
85
- const document = await fetchSolidDocument(documentUrl, options.fetch);
93
+ const document = await fetchSolidDocument(documentUrl, requestOptions);
86
94
 
87
95
  if (!document.isPersonalProfile() && !document.contains(webId, 'solid:oidcIssuer')) {
88
96
  throw new Error(`${webId} is not a valid webId.`);
89
97
  }
90
98
 
91
- const { store, writableProfileUrl, cloaked } = await fetchExtendedUserProfile(document, options.fetch);
99
+ const { store, writableProfileUrl, cloaked } = await fetchExtendedUserProfile(document, options);
92
100
  const storageUrls = store.statements(webId, 'pim:storage').map(storage => storage.object.value);
93
101
  const publicTypeIndex = store.statement(webId, 'solid:publicTypeIndex');
94
102
  const privateTypeIndex = store.statement(webId, 'solid:privateTypeIndex');
95
103
 
96
104
  let parentUrl = urlParentDirectory(documentUrl);
97
105
  while (parentUrl && storageUrls.length === 0) {
98
- const parentDocument = await silenced(fetchSolidDocument(parentUrl, options.fetch));
106
+ const parentDocument = await silenced(fetchSolidDocument(parentUrl, requestOptions));
99
107
 
100
108
  if (parentDocument?.isStorage()) {
101
109
  storageUrls.push(parentUrl);
@@ -110,7 +118,7 @@ async function fetchUserProfile(webId: string, options: FetchUserProfileOptions
110
118
  throw new Error(`Could not find any storage for ${webId}.`);
111
119
  }
112
120
 
113
- await options.onLoaded?.(new SolidStore(store.statements(webId)));
121
+ await options.onLoaded?.(store);
114
122
 
115
123
  return {
116
124
  webId,
@@ -12,7 +12,7 @@ async function mintTypeIndexUrl(user: SolidUserProfile, type: TypeIndexType, fet
12
12
  const storageUrl = user.storageUrls[0];
13
13
  const typeIndexUrl = `${storageUrl}settings/${type}TypeIndex`;
14
14
 
15
- return await solidDocumentExists(typeIndexUrl, fetch)
15
+ return await solidDocumentExists(typeIndexUrl, { fetch })
16
16
  ? `${storageUrl}settings/${type}TypeIndex-${uuid()}`
17
17
  : typeIndexUrl;
18
18
  }
@@ -57,7 +57,7 @@ async function findRegistrations(
57
57
  predicate: string,
58
58
  fetch?: Fetch,
59
59
  ): Promise<string[]> {
60
- const typeIndex = await fetchSolidDocument(typeIndexUrl, fetch);
60
+ const typeIndex = await fetchSolidDocument(typeIndexUrl, { fetch });
61
61
  const types = Array.isArray(type) ? type : [type];
62
62
 
63
63
  return types.map(
package/src/helpers/io.ts CHANGED
@@ -28,13 +28,21 @@ export declare type Fetch = TypedFetch | AnyFetch;
28
28
  const ANONYMOUS_PREFIX = 'anonymous://';
29
29
  const ANONYMOUS_PREFIX_LENGTH = ANONYMOUS_PREFIX.length;
30
30
 
31
- async function fetchRawSolidDocument(url: string, fetch: Fetch): Promise<{ body: string; headers: Headers }> {
32
- const options = {
31
+ async function fetchRawSolidDocument(
32
+ url: string,
33
+ options?: FetchSolidDocumentOptions,
34
+ ): Promise<{ body: string; headers: Headers }> {
35
+ const requestOptions: RequestInit = {
33
36
  headers: { Accept: 'text/turtle' },
34
37
  };
35
38
 
39
+ if (options?.cache) {
40
+ requestOptions.cache = options.cache;
41
+ }
42
+
36
43
  try {
37
- const response = await fetch(url, options);
44
+ const fetch = options?.fetch ?? window.fetch;
45
+ const response = await fetch(url, requestOptions);
38
46
 
39
47
  if (response.status === 404)
40
48
  throw new NotFoundError(url);
@@ -141,6 +149,11 @@ function postprocessSubjects(quads: Quad[]): void {
141
149
  }
142
150
  }
143
151
 
152
+ export interface FetchSolidDocumentOptions {
153
+ fetch?: Fetch;
154
+ cache?: RequestCache;
155
+ }
156
+
144
157
  export interface ParsingOptions {
145
158
  baseIRI: string;
146
159
  normalizeBlankNodes: boolean;
@@ -151,7 +164,6 @@ export interface RDFGraphData {
151
164
  containsRelativeIRIs: boolean;
152
165
  }
153
166
 
154
-
155
167
  export async function createSolidDocument(url: string, body: string, fetch?: Fetch): Promise<SolidDocument> {
156
168
  fetch = fetch ?? window.fetch.bind(window);
157
169
 
@@ -166,16 +178,19 @@ export async function createSolidDocument(url: string, body: string, fetch?: Fet
166
178
  return new SolidDocument(url, statements, new Headers({}));
167
179
  }
168
180
 
169
- export async function fetchSolidDocument(url: string, fetch?: Fetch): Promise<SolidDocument> {
170
- const { body: data, headers } = await fetchRawSolidDocument(url, fetch ?? window.fetch);
181
+ export async function fetchSolidDocument(url: string, options?: FetchSolidDocumentOptions): Promise<SolidDocument> {
182
+ const { body: data, headers } = await fetchRawSolidDocument(url, options);
171
183
  const statements = await turtleToQuads(data, { baseIRI: url });
172
184
 
173
185
  return new SolidDocument(url, statements, headers);
174
186
  }
175
187
 
176
- export async function fetchSolidDocumentIfFound(url: string, fetch?: Fetch): Promise<SolidDocument | null> {
188
+ export async function fetchSolidDocumentIfFound(
189
+ url: string,
190
+ options?: FetchSolidDocumentOptions,
191
+ ): Promise<SolidDocument | null> {
177
192
  try {
178
- const document = await fetchSolidDocument(url, fetch);
193
+ const document = await fetchSolidDocument(url, options);
179
194
 
180
195
  return document;
181
196
  } catch (error) {
@@ -287,9 +302,9 @@ export function quadToTurtle(quad: Quad): string {
287
302
  return writer.quadsToString([quad]).slice(0, -1);
288
303
  }
289
304
 
290
- export async function solidDocumentExists(url: string, fetch?: Fetch): Promise<boolean> {
305
+ export async function solidDocumentExists(url: string, options?: FetchSolidDocumentOptions): Promise<boolean> {
291
306
  try {
292
- const document = await fetchSolidDocument(url, fetch);
307
+ const document = await fetchSolidDocument(url, options);
293
308
 
294
309
  return !document.isEmpty();
295
310
  } catch (error) {
@@ -26,7 +26,7 @@ async function fetchEffectiveACL(
26
26
  ): Promise<SolidDocument> {
27
27
  aclResourceUrl = aclResourceUrl ?? await fetchACLResourceUrl(resourceUrl, fetch);
28
28
 
29
- const aclDocument = await fetchSolidDocumentIfFound(aclResourceUrl ?? '', fetch);
29
+ const aclDocument = await fetchSolidDocumentIfFound(aclResourceUrl ?? '', { fetch });
30
30
 
31
31
  if (!aclDocument) {
32
32
  return fetchEffectiveACL(requireUrlParentDirectory(resourceUrl), fetch);
@@ -1,9 +1,11 @@
1
- import type { Quad } from 'rdf-js';
1
+ import type { BlankNode, Literal, NamedNode, Quad, Variable } from 'rdf-js';
2
2
 
3
3
  import { expandIRI } from '@/helpers/vocabs';
4
4
 
5
5
  import SolidThing from './SolidThing';
6
6
 
7
+ export type Term = NamedNode | Literal | BlankNode | Quad | Variable;
8
+
7
9
  export default class SolidStore {
8
10
 
9
11
  private quads: Quad[];
@@ -24,21 +26,21 @@ export default class SolidStore {
24
26
  this.quads.push(...quads);
25
27
  }
26
28
 
27
- public statements(subject?: string, predicate?: string, object?: string): Quad[] {
29
+ public statements(subject?: Term | string, predicate?: Term | string, object?: Term | string): Quad[] {
28
30
  return this.quads.filter(
29
31
  statement =>
30
- (!object || statement.object.value === this.expandIRI(object)) &&
31
- (!subject || statement.subject.value === this.expandIRI(subject)) &&
32
- (!predicate || statement.predicate.value === this.expandIRI(predicate)),
32
+ (!object || this.termMatches(statement.object, object)) &&
33
+ (!subject || this.termMatches(statement.subject, subject)) &&
34
+ (!predicate || this.termMatches(statement.predicate, predicate)),
33
35
  );
34
36
  }
35
37
 
36
- public statement(subject?: string, predicate?: string, object?: string): Quad | null {
38
+ public statement(subject?: Term | string, predicate?: Term | string, object?: Term | string): Quad | null {
37
39
  const statement = this.quads.find(
38
40
  statement =>
39
- (!object || statement.object.value === this.expandIRI(object)) &&
40
- (!subject || statement.subject.value === this.expandIRI(subject)) &&
41
- (!predicate || statement.predicate.value === this.expandIRI(predicate)),
41
+ (!object || this.termMatches(statement.object, object)) &&
42
+ (!subject || this.termMatches(statement.subject, subject)) &&
43
+ (!predicate || this.termMatches(statement.predicate, predicate)),
42
44
  );
43
45
 
44
46
  return statement ?? null;
@@ -58,4 +60,12 @@ export default class SolidStore {
58
60
  return expandIRI(iri);
59
61
  }
60
62
 
63
+ protected termMatches(term: Term, value: Term | string): boolean {
64
+ if (typeof value === 'string') {
65
+ return this.expandIRI(value) === term.value;
66
+ }
67
+
68
+ return term.termType === term.termType && term.value === value.value;
69
+ }
70
+
61
71
  }
@@ -1,3 +1,5 @@
1
1
  export { default as SolidDocument, SolidDocumentPermission } from './SolidDocument';
2
2
  export { default as SolidStore } from './SolidStore';
3
3
  export { default as SolidThing } from './SolidThing';
4
+
5
+ export * from './SolidStore';