1 | import { Headers } from 'cross-fetch';
|
2 | import LinkHeader from 'http-link-header';
|
3 | import { quad, literal, namedNode, blankNode, dataset } from '@rdfjs/dataset';
|
4 | import { Parser, Writer } from 'n3';
|
5 |
|
6 | /*! *****************************************************************************
|
7 | Copyright (c) Microsoft Corporation.
|
8 |
|
9 | Permission to use, copy, modify, and/or distribute this software for any
|
10 | purpose with or without fee is hereby granted.
|
11 |
|
12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
13 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
14 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
15 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
16 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
17 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
18 | PERFORMANCE OF THIS SOFTWARE.
|
19 | ***************************************************************************** */
|
20 |
|
21 | function __awaiter(thisArg, _arguments, P, generator) {
|
22 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
23 | return new (P || (P = Promise))(function (resolve, reject) {
|
24 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
25 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
26 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
27 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
28 | });
|
29 | }
|
30 |
|
31 | /**
|
32 | * Copyright 2020 Inrupt Inc.
|
33 | *
|
34 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
35 | * of this software and associated documentation files (the "Software"), to deal in
|
36 | * the Software without restriction, including without limitation the rights to use,
|
37 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
38 | * Software, and to permit persons to whom the Software is furnished to do so,
|
39 | * subject to the following conditions:
|
40 | *
|
41 | * The above copyright notice and this permission notice shall be included in
|
42 | * all copies or substantial portions of the Software.
|
43 | *
|
44 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
45 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
46 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
47 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
48 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
49 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
50 | */
|
51 | /**
|
52 | * @ignore Internal fallback for when no fetcher is provided; not to be used downstream.
|
53 | */
|
54 | const fetch = (resource, init) => {
|
55 | // Implementation note: it's up to the client application to resolve these module names to the
|
56 | // respective npm packages. At least one commonly used tool (Webpack) is only able to do that if
|
57 | // the module names are literal strings.
|
58 | // Additionally, Webpack throws a warning in a way that halts compilation for at least Next.js
|
59 | // when using native Javascript dynamic imports (`import()`), whereas `require()` just logs a
|
60 | // warning. Since the use of package names instead of file names requires a bundles anyway, this
|
61 | // should not have any practical consequences. For more background, see:
|
62 | // https://github.com/webpack/webpack/issues/7713
|
63 | let fetch;
|
64 | try {
|
65 | fetch = require("@inrupt/solid-auth-fetcher").fetch;
|
66 | }
|
67 | catch (e) {
|
68 | try {
|
69 | fetch = require("solid-auth-client").fetch;
|
70 | }
|
71 | catch (e) {
|
72 | fetch = require("cross-fetch");
|
73 | }
|
74 | }
|
75 | return fetch(resource, init);
|
76 | };
|
77 |
|
78 | /**
|
79 | * Copyright 2020 Inrupt Inc.
|
80 | *
|
81 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
82 | * of this software and associated documentation files (the "Software"), to deal in
|
83 | * the Software without restriction, including without limitation the rights to use,
|
84 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
85 | * Software, and to permit persons to whom the Software is furnished to do so,
|
86 | * subject to the following conditions:
|
87 | *
|
88 | * The above copyright notice and this permission notice shall be included in
|
89 | * all copies or substantial portions of the Software.
|
90 | *
|
91 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
92 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
93 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
94 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
95 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
96 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
97 | */
|
98 | const defaultFetchFileOptions = {
|
99 | fetch: fetch,
|
100 | };
|
101 | const RESERVED_HEADERS = ["Slug", "If-None-Match", "Content-Type"];
|
102 | /**
|
103 | * Some of the headers must be set by the library, rather than directly.
|
104 | */
|
105 | function containsReserved(header) {
|
106 | return RESERVED_HEADERS.some((reserved) => header.has(reserved));
|
107 | }
|
108 | /**
|
109 | * Fetches a file at a given URL, and returns it as a blob of data.
|
110 | *
|
111 | * Please note that this function is still experimental: its API can change in non-major releases.
|
112 | *
|
113 | * @param url The URL of the fetched file
|
114 | * @param options Fetching options: a custom fetcher and/or headers.
|
115 | */
|
116 | function unstable_fetchFile(input, options = defaultFetchFileOptions) {
|
117 | return __awaiter(this, void 0, void 0, function* () {
|
118 | const config = Object.assign(Object.assign({}, defaultFetchFileOptions), options);
|
119 | return config.fetch(input, config.init);
|
120 | });
|
121 | }
|
122 | /**
|
123 | * Deletes a file at a given URL
|
124 | *
|
125 | * Please note that this function is still experimental: its API can change in non-major releases.
|
126 | *
|
127 | * @param input The URL of the file to delete
|
128 | */
|
129 | function unstable_deleteFile(input, options = defaultFetchFileOptions) {
|
130 | return __awaiter(this, void 0, void 0, function* () {
|
131 | const config = Object.assign(Object.assign({}, defaultFetchFileOptions), options);
|
132 | return config.fetch(input, Object.assign(Object.assign({}, config.init), { method: "DELETE" }));
|
133 | });
|
134 | }
|
135 | /**
|
136 | * Saves a file in a folder at a given URL. The server will return the final
|
137 | * filename (which may or may not be the given `slug`), it will return it in
|
138 | * the response's Location header.
|
139 | *
|
140 | * @param folderUrl The URL of the folder where the new file is saved
|
141 | * @param file The file to be written
|
142 | * @param options Additional parameters for file creation (e.g. a slug)
|
143 | */
|
144 | function unstable_saveFileInContainer(folderUrl, file, options = defaultFetchFileOptions) {
|
145 | return __awaiter(this, void 0, void 0, function* () {
|
146 | return writeFile(folderUrl, file, "POST", options);
|
147 | });
|
148 | }
|
149 | /**
|
150 | * Saves a file at a given URL, erasing any previous content.
|
151 | *
|
152 | * @param fileUrl The URL where the file is saved
|
153 | * @param file The file to be written
|
154 | * @param options Additional parameters for file creation (e.g. a slug)
|
155 | */
|
156 | function unstable_overwriteFile(fileUrl, file, options = defaultFetchFileOptions) {
|
157 | return __awaiter(this, void 0, void 0, function* () {
|
158 | return writeFile(fileUrl, file, "PUT", options);
|
159 | });
|
160 | }
|
161 | /**
|
162 | * Internal function that performs the actual write HTTP query, either POST
|
163 | * or PUT depending on the use case.
|
164 | *
|
165 | * @param fileUrl The URL where the file is saved
|
166 | * @param file The file to be written
|
167 | * @param method The HTTP method
|
168 | * @param options Additional parameters for file creation (e.g. a slug)
|
169 | */
|
170 | function writeFile(targetUrl, file, method, options) {
|
171 | var _a, _b;
|
172 | return __awaiter(this, void 0, void 0, function* () {
|
173 | const config = Object.assign(Object.assign({}, defaultFetchFileOptions), options);
|
174 | const headers = new Headers((_b = (_a = config.init) === null || _a === void 0 ? void 0 : _a.headers) !== null && _b !== void 0 ? _b : {});
|
175 | if (containsReserved(headers)) {
|
176 | throw new Error(`No reserved header (${RESERVED_HEADERS.join(", ")}) should be set in the optional RequestInit.`);
|
177 | }
|
178 | // If a slug is in the parameters, set the request headers accordingly
|
179 | if (config.slug !== undefined) {
|
180 | headers.append("Slug", config.slug);
|
181 | }
|
182 | headers.append("Content-Type", file.type);
|
183 | return yield config.fetch(targetUrl, Object.assign(Object.assign({}, config.init), { headers,
|
184 | method, body: file }));
|
185 | });
|
186 | }
|
187 |
|
188 | /**
|
189 | * Copyright 2020 Inrupt Inc.
|
190 | *
|
191 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
192 | * of this software and associated documentation files (the "Software"), to deal in
|
193 | * the Software without restriction, including without limitation the rights to use,
|
194 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
195 | * Software, and to permit persons to whom the Software is furnished to do so,
|
196 | * subject to the following conditions:
|
197 | *
|
198 | * The above copyright notice and this permission notice shall be included in
|
199 | * all copies or substantial portions of the Software.
|
200 | *
|
201 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
202 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
203 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
204 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
205 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
206 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
207 | */
|
208 | /**
|
209 | * @internal
|
210 | */
|
211 | const DataFactory = { quad, literal, namedNode, blankNode };
|
212 | /**
|
213 | * Clone a Dataset.
|
214 | *
|
215 | * Note that the Quads are not cloned, i.e. if you modify the Quads in the output Dataset, the Quads
|
216 | * in the input Dataset will also be changed.
|
217 | *
|
218 | * @internal
|
219 | * @param input Dataset to clone.
|
220 | * @returns A new Dataset with the same Quads as `input`.
|
221 | */
|
222 | function clone(input) {
|
223 | const output = dataset();
|
224 | for (const quad of input) {
|
225 | output.add(quad);
|
226 | }
|
227 | return output;
|
228 | }
|
229 | /**
|
230 | * @internal
|
231 | * @param input Dataset to clone.
|
232 | * @param callback Function that takes a Quad, and returns a boolean indicating whether that Quad should be included in the cloned Dataset.
|
233 | * @returns A new Dataset with the same Quads as `input`, excluding the ones for which `callback` returned `false`.
|
234 | */
|
235 | function filter(input, callback) {
|
236 | const output = dataset();
|
237 | for (const quad of input) {
|
238 | if (callback(quad)) {
|
239 | output.add(quad);
|
240 | }
|
241 | }
|
242 | return output;
|
243 | }
|
244 |
|
245 | /**
|
246 | * Copyright 2020 Inrupt Inc.
|
247 | *
|
248 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
249 | * of this software and associated documentation files (the "Software"), to deal in
|
250 | * the Software without restriction, including without limitation the rights to use,
|
251 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
252 | * Software, and to permit persons to whom the Software is furnished to do so,
|
253 | * subject to the following conditions:
|
254 | *
|
255 | * The above copyright notice and this permission notice shall be included in
|
256 | * all copies or substantial portions of the Software.
|
257 | *
|
258 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
259 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
260 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
261 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
262 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
263 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
264 | */
|
265 | /**
|
266 | * @param quads Triples that should be serialised to Turtle
|
267 | * @internal Utility method for internal use; not part of the public API.
|
268 | */
|
269 | function triplesToTurtle(quads) {
|
270 | return __awaiter(this, void 0, void 0, function* () {
|
271 | const format = "text/turtle";
|
272 | const writer = new Writer({ format: format });
|
273 | // Remove any potentially lingering references to Named Graphs in Quads;
|
274 | // they'll be determined by the URL the Turtle will be sent to:
|
275 | const triples = quads.map((quad) => DataFactory.quad(quad.subject, quad.predicate, quad.object, undefined));
|
276 | writer.addQuads(triples);
|
277 | const writePromise = new Promise((resolve, reject) => {
|
278 | writer.end((error, result) => {
|
279 | /* istanbul ignore if [n3.js doesn't actually pass an error nor a result, apparently: https://github.com/rdfjs/N3.js/blob/62682e48c02d8965b4d728cb5f2cbec6b5d1b1b8/src/N3Writer.js#L290] */
|
280 | if (error) {
|
281 | return reject(error);
|
282 | }
|
283 | resolve(result);
|
284 | });
|
285 | });
|
286 | const rawTurtle = yield writePromise;
|
287 | return rawTurtle;
|
288 | });
|
289 | }
|
290 | /**
|
291 | * @param raw Turtle that should be parsed into Triples
|
292 | * @internal Utility method for internal use; not part of the public API.
|
293 | */
|
294 | function turtleToTriples(raw, resourceIri) {
|
295 | return __awaiter(this, void 0, void 0, function* () {
|
296 | const format = "text/turtle";
|
297 | const parser = new Parser({ format: format, baseIRI: resourceIri });
|
298 | const parsingPromise = new Promise((resolve, reject) => {
|
299 | const parsedTriples = [];
|
300 | parser.parse(raw, (error, triple, _prefixes) => {
|
301 | if (error) {
|
302 | return reject(error);
|
303 | }
|
304 | if (triple) {
|
305 | parsedTriples.push(triple);
|
306 | }
|
307 | else {
|
308 | resolve(parsedTriples);
|
309 | }
|
310 | });
|
311 | });
|
312 | return parsingPromise;
|
313 | });
|
314 | }
|
315 |
|
316 | /**
|
317 | * Copyright 2020 Inrupt Inc.
|
318 | *
|
319 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
320 | * of this software and associated documentation files (the "Software"), to deal in
|
321 | * the Software without restriction, including without limitation the rights to use,
|
322 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
323 | * Software, and to permit persons to whom the Software is furnished to do so,
|
324 | * subject to the following conditions:
|
325 | *
|
326 | * The above copyright notice and this permission notice shall be included in
|
327 | * all copies or substantial portions of the Software.
|
328 | *
|
329 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
330 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
331 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
332 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
333 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
334 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
335 | */
|
336 | /**
|
337 | * IRIs of the XML Schema data types we support
|
338 | * @internal
|
339 | */
|
340 | const xmlSchemaTypes = {
|
341 | boolean: "http://www.w3.org/2001/XMLSchema#boolean",
|
342 | dateTime: "http://www.w3.org/2001/XMLSchema#dateTime",
|
343 | decimal: "http://www.w3.org/2001/XMLSchema#decimal",
|
344 | integer: "http://www.w3.org/2001/XMLSchema#integer",
|
345 | string: "http://www.w3.org/2001/XMLSchema#string",
|
346 | langString: "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString",
|
347 | };
|
348 | /**
|
349 | * @internal
|
350 | * @param value Value to serialise.
|
351 | * @returns String representation of `value`.
|
352 | */
|
353 | function serializeBoolean(value) {
|
354 | return value ? "1" : "0";
|
355 | }
|
356 | /**
|
357 | * @internal
|
358 | * @param value Value to deserialise.
|
359 | * @returns Deserialized boolean, or null if the given value is not a valid serialised boolean.
|
360 | */
|
361 | function deserializeBoolean(value) {
|
362 | if (value === "1") {
|
363 | return true;
|
364 | }
|
365 | else if (value === "0") {
|
366 | return false;
|
367 | }
|
368 | else {
|
369 | return null;
|
370 | }
|
371 | }
|
372 | /**
|
373 | * @internal
|
374 | * @param value Value to serialise.
|
375 | * @returns String representation of `value`.
|
376 | */
|
377 | function serializeDatetime(value) {
|
378 | // To align with rdflib, we ignore miliseconds:
|
379 | // https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L74
|
380 | const roundedDate = new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate(), value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), 0));
|
381 | // Truncate the `.000Z` at the end (i.e. the miliseconds), to plain `Z`:
|
382 | const rdflibStyleString = roundedDate.toISOString().replace(/\.000Z$/, "Z");
|
383 | return rdflibStyleString;
|
384 | }
|
385 | /**
|
386 | * @internal
|
387 | * @param value Value to deserialise.
|
388 | * @returns Deserialized datetime, or null if the given value is not a valid serialised datetime.
|
389 | */
|
390 | function deserializeDatetime(literalString) {
|
391 | if (literalString === null ||
|
392 | literalString.length <= 17 ||
|
393 | literalString.indexOf("Z") === -1) {
|
394 | return null;
|
395 | }
|
396 | // See https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L87
|
397 | const utcFullYear = parseInt(literalString.substring(0, 4), 10);
|
398 | const utcMonth = parseInt(literalString.substring(5, 7), 10) - 1;
|
399 | const utcDate = parseInt(literalString.substring(8, 10), 10);
|
400 | const utcHours = parseInt(literalString.substring(11, 13), 10);
|
401 | const utcMinutes = parseInt(literalString.substring(14, 16), 10);
|
402 | const utcSeconds = parseInt(literalString.substring(17, literalString.indexOf("Z")), 10);
|
403 | const date = new Date(0);
|
404 | date.setUTCFullYear(utcFullYear);
|
405 | date.setUTCMonth(utcMonth);
|
406 | date.setUTCDate(utcDate);
|
407 | date.setUTCHours(utcHours);
|
408 | date.setUTCMinutes(utcMinutes);
|
409 | date.setUTCSeconds(utcSeconds);
|
410 | return date;
|
411 | }
|
412 | /**
|
413 | * @internal
|
414 | * @param value Value to serialise.
|
415 | * @returns String representation of `value`.
|
416 | */
|
417 | function serializeDecimal(value) {
|
418 | return value.toString();
|
419 | }
|
420 | /**
|
421 | * @internal
|
422 | * @param value Value to deserialise.
|
423 | * @returns Deserialized decimal, or null if the given value is not a valid serialised decimal.
|
424 | */
|
425 | function deserializeDecimal(literalString) {
|
426 | const deserialized = Number.parseFloat(literalString);
|
427 | if (Number.isNaN(deserialized)) {
|
428 | return null;
|
429 | }
|
430 | return deserialized;
|
431 | }
|
432 | /**
|
433 | * @internal
|
434 | * @param value Value to serialise.
|
435 | * @returns String representation of `value`.
|
436 | */
|
437 | function serializeInteger(value) {
|
438 | return value.toString();
|
439 | }
|
440 | /**
|
441 | * @internal
|
442 | * @param value Value to deserialise.
|
443 | * @returns Deserialized integer, or null if the given value is not a valid serialised integer.
|
444 | */
|
445 | function deserializeInteger(literalString) {
|
446 | const deserialized = Number.parseInt(literalString, 10);
|
447 | if (Number.isNaN(deserialized)) {
|
448 | return null;
|
449 | }
|
450 | return deserialized;
|
451 | }
|
452 | /**
|
453 | * @internal
|
454 | * @param locale Locale to transform into a consistent format.
|
455 | */
|
456 | function normalizeLocale(locale) {
|
457 | return locale.toLowerCase();
|
458 | }
|
459 | /**
|
460 | * @internal Library users shouldn't need to be exposed to raw NamedNodes.
|
461 | * @param value The value that might or might not be a Named Node.
|
462 | * @returns Whether `value` is a Named Node.
|
463 | */
|
464 | function isNamedNode(value) {
|
465 | return (typeof value === "object" &&
|
466 | typeof value.termType === "string" &&
|
467 | value.termType === "NamedNode");
|
468 | }
|
469 | /**
|
470 | * @internal Library users shouldn't need to be exposed to raw Literals.
|
471 | * @param value The value that might or might not be a Literal.
|
472 | * @returns Whether `value` is a Literal.
|
473 | */
|
474 | function isLiteral(value) {
|
475 | return (typeof value === "object" &&
|
476 | typeof value.termType === "string" &&
|
477 | value.termType === "Literal");
|
478 | }
|
479 | /**
|
480 | * @internal Library users shouldn't need to be exposed to LocalNodes.
|
481 | * @param value The value that might or might not be a Node with no known IRI yet.
|
482 | * @returns Whether `value` is a Node with no known IRI yet.
|
483 | */
|
484 | function isLocalNode(value) {
|
485 | return (typeof value === "object" &&
|
486 | typeof value.termType === "string" &&
|
487 | value.termType === "BlankNode" &&
|
488 | typeof value.name === "string");
|
489 | }
|
490 | /**
|
491 | * Construct a new LocalNode.
|
492 | *
|
493 | * @internal Library users shouldn't need to be exposed to LocalNodes.
|
494 | * @param name Name to identify this node by.
|
495 | * @returns A LocalNode whose name will be resolved when it is persisted to a Pod.
|
496 | */
|
497 | function getLocalNode(name) {
|
498 | const localNode = Object.assign(DataFactory.blankNode(), {
|
499 | name: name,
|
500 | });
|
501 | return localNode;
|
502 | }
|
503 | /**
|
504 | * Ensure that a given value is a Named Node.
|
505 | *
|
506 | * If the given parameter is a Named Node already, it will be returned as-is. If it is a string, it
|
507 | * will check whether it is a valid IRI. If not, it will throw an error; otherwise a Named Node
|
508 | * representing the given IRI will be returned.
|
509 | *
|
510 | * @internal Library users shouldn't need to be exposed to raw NamedNodes.
|
511 | * @param iri The IRI that should be converted into a Named Node, if it isn't one yet.
|
512 | */
|
513 | function asNamedNode(iri) {
|
514 | if (isNamedNode(iri)) {
|
515 | return iri;
|
516 | }
|
517 | // If the runtime environment supports URL, instantiate one.
|
518 | // If thte given IRI is not a valid URL, it will throw an error.
|
519 | // See: https://developer.mozilla.org/en-US/docs/Web/API/URL
|
520 | /* istanbul ignore else [URL is available in our testing environment, so we cannot test the alternative] */
|
521 | if (typeof URL !== "undefined") {
|
522 | new URL(iri);
|
523 | }
|
524 | return DataFactory.namedNode(iri);
|
525 | }
|
526 | /**
|
527 | * Check whether two current- or potential NamedNodes are/will be equal.
|
528 | *
|
529 | * @internal Utility method; library users should not need to interact with LocalNodes directly.
|
530 | */
|
531 | function isEqual(node1, node2, options = {}) {
|
532 | if (isNamedNode(node1) && isNamedNode(node2)) {
|
533 | return node1.equals(node2);
|
534 | }
|
535 | if (isLocalNode(node1) && isLocalNode(node2)) {
|
536 | return node1.name === node2.name;
|
537 | }
|
538 | if (typeof options.resourceIri === "undefined") {
|
539 | // If we don't know what IRI to resolve the LocalNode to,
|
540 | // we cannot conclude that it is equal to the NamedNode's full IRI:
|
541 | return false;
|
542 | }
|
543 | const namedNode1 = isNamedNode(node1)
|
544 | ? node1
|
545 | : resolveIriForLocalNode(node1, options.resourceIri);
|
546 | const namedNode2 = isNamedNode(node2)
|
547 | ? node2
|
548 | : resolveIriForLocalNode(node2, options.resourceIri);
|
549 | return namedNode1.equals(namedNode2);
|
550 | }
|
551 | /**
|
552 | * @internal Utility method; library users should not need to interact with LocalNodes directly.
|
553 | * @param quad The Quad to resolve LocalNodes in.
|
554 | * @param resourceIri The IRI of the Resource to resolve the LocalNodes against.
|
555 | */
|
556 | function resolveIriForLocalNodes(quad, resourceIri) {
|
557 | const subject = isLocalNode(quad.subject)
|
558 | ? resolveIriForLocalNode(quad.subject, resourceIri)
|
559 | : quad.subject;
|
560 | const object = isLocalNode(quad.object)
|
561 | ? resolveIriForLocalNode(quad.object, resourceIri)
|
562 | : quad.object;
|
563 | return Object.assign(Object.assign({}, quad), { subject: subject, object: object });
|
564 | }
|
565 | /**
|
566 | * @internal Utility method; library users should not need to interact with LocalNodes directly.
|
567 | * @param localNode The LocalNode to resolve to a NamedNode.
|
568 | * @param resourceIri The Resource in which the Node will be saved.
|
569 | */
|
570 | function resolveIriForLocalNode(localNode, resourceIri) {
|
571 | return DataFactory.namedNode(resolveLocalIri(localNode.name, resourceIri));
|
572 | }
|
573 | /**
|
574 | * @internal API for internal use only.
|
575 | * @param name The name identifying a Thing.
|
576 | * @param resourceIri The Resource in which the Thing can be found.
|
577 | */
|
578 | function resolveLocalIri(name, resourceIri) {
|
579 | /* istanbul ignore if [The URL interface is available in the testing environment, so we cannot test this] */
|
580 | if (typeof URL === "undefined") {
|
581 | throw new Error("The URL interface is not available, so an IRI cannot be determined.");
|
582 | }
|
583 | const thingIri = new URL(resourceIri);
|
584 | thingIri.hash = name;
|
585 | return thingIri.href;
|
586 | }
|
587 |
|
588 | /**
|
589 | * Copyright 2020 Inrupt Inc.
|
590 | *
|
591 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
592 | * of this software and associated documentation files (the "Software"), to deal in
|
593 | * the Software without restriction, including without limitation the rights to use,
|
594 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
595 | * Software, and to permit persons to whom the Software is furnished to do so,
|
596 | * subject to the following conditions:
|
597 | *
|
598 | * The above copyright notice and this permission notice shall be included in
|
599 | * all copies or substantial portions of the Software.
|
600 | *
|
601 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
602 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
603 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
604 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
605 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
606 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
607 | */
|
608 | // TODO: These should be replaced by auto-generated constants,
|
609 | // if we can ensure that unused constants will be excluded from bundles.
|
610 | /** @internal */
|
611 | const acl = {
|
612 | Authorization: "http://www.w3.org/ns/auth/acl#Authorization",
|
613 | accessTo: "http://www.w3.org/ns/auth/acl#accessTo",
|
614 | agent: "http://www.w3.org/ns/auth/acl#agent",
|
615 | default: "http://www.w3.org/ns/auth/acl#default",
|
616 | mode: "http://www.w3.org/ns/auth/acl#mode",
|
617 | };
|
618 | /** @internal */
|
619 | const rdf = {
|
620 | type: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
621 | };
|
622 |
|
623 | /**
|
624 | * Copyright 2020 Inrupt Inc.
|
625 | *
|
626 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
627 | * of this software and associated documentation files (the "Software"), to deal in
|
628 | * the Software without restriction, including without limitation the rights to use,
|
629 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
630 | * Software, and to permit persons to whom the Software is furnished to do so,
|
631 | * subject to the following conditions:
|
632 | *
|
633 | * The above copyright notice and this permission notice shall be included in
|
634 | * all copies or substantial portions of the Software.
|
635 | *
|
636 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
637 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
638 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
639 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
640 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
641 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
642 | */
|
643 | /**
|
644 | * Verify whether a given LitDataset includes metadata about where it was retrieved from.
|
645 | *
|
646 | * @param dataset A [[LitDataset]] that may have metadata attached about the Resource it was retrieved from.
|
647 | * @returns True if `dataset` includes metadata about the Resource it was retrieved from, false if not.
|
648 | */
|
649 | function hasDatasetInfo(dataset) {
|
650 | const potentialDatasetInfo = dataset;
|
651 | return typeof potentialDatasetInfo.datasetInfo === "object";
|
652 | }
|
653 | /** @internal */
|
654 | function hasChangelog(dataset) {
|
655 | const potentialChangeLog = dataset;
|
656 | return (typeof potentialChangeLog.changeLog === "object" &&
|
657 | Array.isArray(potentialChangeLog.changeLog.additions) &&
|
658 | Array.isArray(potentialChangeLog.changeLog.deletions));
|
659 | }
|
660 | /**
|
661 | * Given a [[LitDataset]], verify whether it has ACL data attached to it.
|
662 | *
|
663 | * This should generally only be true for LitDatasets fetched by
|
664 | * [[unstable_fetchLitDatasetWithAcl]].
|
665 | *
|
666 | * @param dataset A [[LitDataset]].
|
667 | * @returns Whether the given `dataset` has ACL data attached to it.
|
668 | * @internal
|
669 | */
|
670 | function unstable_hasAccessibleAcl(dataset) {
|
671 | return typeof dataset.datasetInfo.unstable_aclUrl === "string";
|
672 | }
|
673 |
|
674 | /**
|
675 | * Copyright 2020 Inrupt Inc.
|
676 | *
|
677 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
678 | * of this software and associated documentation files (the "Software"), to deal in
|
679 | * the Software without restriction, including without limitation the rights to use,
|
680 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
681 | * Software, and to permit persons to whom the Software is furnished to do so,
|
682 | * subject to the following conditions:
|
683 | *
|
684 | * The above copyright notice and this permission notice shall be included in
|
685 | * all copies or substantial portions of the Software.
|
686 | *
|
687 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
688 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
689 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
690 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
691 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
692 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
693 | */
|
694 | /**
|
695 | * Extract Quads with a given Subject from a [[LitDataset]] into a [[Thing]].
|
696 | *
|
697 | * @param litDataset The [[LitDataset]] to extract the [[Thing]] from.
|
698 | * @param thingUrl The URL of the desired [[Thing]].
|
699 | * @param options Not yet implemented.
|
700 | */
|
701 | function getThingOne(litDataset, thingUrl, options = {}) {
|
702 | const subject = isLocalNode(thingUrl) ? thingUrl : asNamedNode(thingUrl);
|
703 | const scope = options.scope
|
704 | ? asNamedNode(options.scope)
|
705 | : null;
|
706 | const thingDataset = litDataset.match(subject, null, null, scope);
|
707 | if (isLocalNode(subject)) {
|
708 | const thing = Object.assign(thingDataset, {
|
709 | name: subject.name,
|
710 | });
|
711 | return thing;
|
712 | }
|
713 | else {
|
714 | const thing = Object.assign(thingDataset, {
|
715 | url: subject.value,
|
716 | });
|
717 | return thing;
|
718 | }
|
719 | }
|
720 | /**
|
721 | * Get all [[Thing]]s about which a [[LitDataset]] contains Quads.
|
722 | *
|
723 | * @param litDataset The [[LitDataset]] to extract the [[Thing]]s from.
|
724 | * @param options Not yet implemented.
|
725 | */
|
726 | function getThingAll(litDataset, options = {}) {
|
727 | const subjectNodes = new Array();
|
728 | for (const quad of litDataset) {
|
729 | // Because NamedNode objects with the same IRI are actually different
|
730 | // object instances, we have to manually check whether `subjectNodes` does
|
731 | // not yet include `quadSubject` before adding it.
|
732 | const quadSubject = quad.subject;
|
733 | if (isNamedNode(quadSubject) &&
|
734 | !subjectNodes.some((subjectNode) => isEqual(subjectNode, quadSubject))) {
|
735 | subjectNodes.push(quadSubject);
|
736 | }
|
737 | if (isLocalNode(quadSubject) &&
|
738 | !subjectNodes.some((subjectNode) => isEqual(subjectNode, quadSubject))) {
|
739 | subjectNodes.push(quadSubject);
|
740 | }
|
741 | }
|
742 | const things = subjectNodes.map((subjectNode) => getThingOne(litDataset, subjectNode, options));
|
743 | return things;
|
744 | }
|
745 | /**
|
746 | * Insert a [[Thing]] into a [[LitDataset]], replacing previous instances of that Thing.
|
747 | *
|
748 | * @param litDataset The LitDataset to insert a Thing into.
|
749 | * @param thing The Thing to insert into the given LitDataset.
|
750 | * @returns A new LitDataset equal to the given LitDataset, but with the given Thing.
|
751 | */
|
752 | function setThing(litDataset, thing) {
|
753 | const newDataset = removeThing(litDataset, thing);
|
754 | for (const quad of thing) {
|
755 | newDataset.add(quad);
|
756 | newDataset.changeLog.additions.push(quad);
|
757 | }
|
758 | return newDataset;
|
759 | }
|
760 | /**
|
761 | * Remove a Thing from a LitDataset.
|
762 | *
|
763 | * @param litDataset The LitDataset to remove a Thing from.
|
764 | * @param thing The Thing to remove from `litDataset`.
|
765 | * @returns A new [[LitDataset]] equal to the input LitDataset, excluding the given Thing.
|
766 | */
|
767 | function removeThing(litDataset, thing) {
|
768 | const newLitDataset = withChangeLog(cloneLitStructs(litDataset));
|
769 | const resourceIri = hasDatasetInfo(newLitDataset)
|
770 | ? newLitDataset.datasetInfo.fetchedFrom
|
771 | : undefined;
|
772 | const thingSubject = toNode(thing);
|
773 | for (const quad of litDataset) {
|
774 | if (!isNamedNode(quad.subject) && !isLocalNode(quad.subject)) {
|
775 | // This data is unexpected, and hence unlikely to be added by us. Thus, leave it intact:
|
776 | newLitDataset.add(quad);
|
777 | }
|
778 | else if (!isEqual(thingSubject, quad.subject, { resourceIri: resourceIri })) {
|
779 | newLitDataset.add(quad);
|
780 | }
|
781 | else {
|
782 | newLitDataset.changeLog.deletions.push(quad);
|
783 | }
|
784 | }
|
785 | return newLitDataset;
|
786 | }
|
787 | function withChangeLog(litDataset) {
|
788 | const newLitDataset = hasChangelog(litDataset)
|
789 | ? litDataset
|
790 | : Object.assign(litDataset, {
|
791 | changeLog: { additions: [], deletions: [] },
|
792 | });
|
793 | return newLitDataset;
|
794 | }
|
795 | function cloneLitStructs(litDataset) {
|
796 | const freshDataset = dataset();
|
797 | if (hasChangelog(litDataset)) {
|
798 | freshDataset.changeLog = {
|
799 | additions: [...litDataset.changeLog.additions],
|
800 | deletions: [...litDataset.changeLog.deletions],
|
801 | };
|
802 | }
|
803 | if (hasDatasetInfo(litDataset)) {
|
804 | freshDataset.datasetInfo = Object.assign({}, litDataset.datasetInfo);
|
805 | }
|
806 | return freshDataset;
|
807 | }
|
808 | function createThing(options = {}) {
|
809 | var _a;
|
810 | if (typeof options.url !== "undefined") {
|
811 | const url = options.url;
|
812 | /* istanbul ignore else [URL is defined is the testing environment, so we cannot test this] */
|
813 | if (typeof URL !== "undefined") {
|
814 | // Throws an error if the IRI is invalid:
|
815 | new URL(url);
|
816 | }
|
817 | const thing = Object.assign(dataset(), { url: url });
|
818 | return thing;
|
819 | }
|
820 | const name = (_a = options.name) !== null && _a !== void 0 ? _a : generateName();
|
821 | const thing = Object.assign(dataset(), { name: name });
|
822 | return thing;
|
823 | }
|
824 | function asUrl(thing, baseUrl) {
|
825 | if (isThingLocal(thing)) {
|
826 | if (typeof baseUrl === "undefined") {
|
827 | throw new Error("The URL of a Thing that has not been persisted cannot be determined without a base URL.");
|
828 | }
|
829 | return resolveLocalIri(thing.name, baseUrl);
|
830 | }
|
831 | return thing.url;
|
832 | }
|
833 | /** @hidden Alias of [[asUrl]] for those who prefer IRI terminology. */
|
834 | const asIri = asUrl;
|
835 | /**
|
836 | * @param thing The [[Thing]] of which a URL might or might not be known.
|
837 | * @return Whether `thing` has no known URL yet.
|
838 | */
|
839 | function isThingLocal(thing) {
|
840 | return (typeof thing.name === "string" &&
|
841 | typeof thing.url === "undefined");
|
842 | }
|
843 | /**
|
844 | * @internal
|
845 | * @param thing The Thing whose Subject Node you're interested in.
|
846 | * @returns A Node that can be used as the Subject for this Thing's Quads.
|
847 | */
|
848 | function toNode(thing) {
|
849 | if (isNamedNode(thing) || isLocalNode(thing)) {
|
850 | return thing;
|
851 | }
|
852 | if (typeof thing === "string") {
|
853 | return asNamedNode(thing);
|
854 | }
|
855 | if (isThingLocal(thing)) {
|
856 | return getLocalNode(thing.name);
|
857 | }
|
858 | return asNamedNode(asUrl(thing));
|
859 | }
|
860 | function cloneThing(thing) {
|
861 | const cloned = clone(thing);
|
862 | if (isThingLocal(thing)) {
|
863 | cloned.name = thing.name;
|
864 | return cloned;
|
865 | }
|
866 | cloned.url = thing.url;
|
867 | return cloned;
|
868 | }
|
869 | function filterThing(thing, callback) {
|
870 | const filtered = filter(thing, callback);
|
871 | if (isThingLocal(thing)) {
|
872 | filtered.name = thing.name;
|
873 | return filtered;
|
874 | }
|
875 | filtered.url = thing.url;
|
876 | return filtered;
|
877 | }
|
878 | /**
|
879 | * Generate a string that can be used as the unique identifier for a Thing
|
880 | *
|
881 | * This function works by starting with a date string (so that Things can be
|
882 | * sorted chronologically), followed by a random number generated by taking a
|
883 | * random number between 0 and 1, and cutting off the `0.`.
|
884 | *
|
885 | * @internal
|
886 | * @returns An string that's likely to be unique
|
887 | */
|
888 | const generateName = () => {
|
889 | return (Date.now().toString() + Math.random().toString().substring("0.".length));
|
890 | };
|
891 |
|
892 | /**
|
893 | * Copyright 2020 Inrupt Inc.
|
894 | *
|
895 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
896 | * of this software and associated documentation files (the "Software"), to deal in
|
897 | * the Software without restriction, including without limitation the rights to use,
|
898 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
899 | * Software, and to permit persons to whom the Software is furnished to do so,
|
900 | * subject to the following conditions:
|
901 | *
|
902 | * The above copyright notice and this permission notice shall be included in
|
903 | * all copies or substantial portions of the Software.
|
904 | *
|
905 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
906 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
907 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
908 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
909 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
910 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
911 | */
|
912 | /**
|
913 | * @param thing The [[Thing]] to read a URL value from.
|
914 | * @param predicate The given Predicate for which you want the URL value.
|
915 | * @returns A URL value for the given Predicate, if present, or null otherwise.
|
916 | */
|
917 | function getUrlOne(thing, predicate) {
|
918 | const namedNodeMatcher = getNamedNodeMatcher(predicate);
|
919 | const matchingQuad = findOne(thing, namedNodeMatcher);
|
920 | if (matchingQuad === null) {
|
921 | return null;
|
922 | }
|
923 | return matchingQuad.object.value;
|
924 | }
|
925 | /** @hidden Alias of [[getUrlOne]] for those who prefer IRI terminology. */
|
926 | const getIriOne = getUrlOne;
|
927 | /**
|
928 | * @param thing The [[Thing]] to read the URL values from.
|
929 | * @param predicate The given Predicate for which you want the URL values.
|
930 | * @returns The URL values for the given Predicate.
|
931 | */
|
932 | function getUrlAll(thing, predicate) {
|
933 | const iriMatcher = getNamedNodeMatcher(predicate);
|
934 | const matchingQuads = findAll(thing, iriMatcher);
|
935 | return matchingQuads.map((quad) => quad.object.value);
|
936 | }
|
937 | /** @hidden Alias of [[getUrlAll]] for those who prefer IRI terminology. */
|
938 | const getIriAll = getUrlAll;
|
939 | /**
|
940 | * @param thing The [[Thing]] to read a boolean value from.
|
941 | * @param predicate The given Predicate for which you want the boolean value.
|
942 | * @returns A boolean value for the given Predicate, if present, or null otherwise.
|
943 | */
|
944 | function getBooleanOne(thing, predicate) {
|
945 | const literalString = getLiteralOneOfType(thing, predicate, xmlSchemaTypes.boolean);
|
946 | if (literalString === null) {
|
947 | return null;
|
948 | }
|
949 | return deserializeBoolean(literalString);
|
950 | }
|
951 | /**
|
952 | * @param thing The [[Thing]] to read the boolean values from.
|
953 | * @param predicate The given Predicate for which you want the boolean values.
|
954 | * @returns The boolean values for the given Predicate.
|
955 | */
|
956 | function getBooleanAll(thing, predicate) {
|
957 | const literalStrings = getLiteralAllOfType(thing, predicate, xmlSchemaTypes.boolean);
|
958 | return literalStrings
|
959 | .map(deserializeBoolean)
|
960 | .filter((possibleBoolean) => possibleBoolean !== null);
|
961 | }
|
962 | /**
|
963 | * @param thing The [[Thing]] to read a datetime value from.
|
964 | * @param predicate The given Predicate for which you want the datetime value.
|
965 | * @returns A datetime value for the given Predicate, if present, or null otherwise.
|
966 | */
|
967 | function getDatetimeOne(thing, predicate) {
|
968 | const literalString = getLiteralOneOfType(thing, predicate, xmlSchemaTypes.dateTime);
|
969 | if (literalString === null) {
|
970 | return null;
|
971 | }
|
972 | return deserializeDatetime(literalString);
|
973 | }
|
974 | /**
|
975 | * @param thing The [[Thing]] to read the datetime values from.
|
976 | * @param predicate The given Predicate for which you want the datetime values.
|
977 | * @returns The datetime values for the given Predicate.
|
978 | */
|
979 | function getDatetimeAll(thing, predicate) {
|
980 | const literalStrings = getLiteralAllOfType(thing, predicate, xmlSchemaTypes.dateTime);
|
981 | return literalStrings
|
982 | .map(deserializeDatetime)
|
983 | .filter((potentialDatetime) => potentialDatetime !== null);
|
984 | }
|
985 | /**
|
986 | * @param thing The [[Thing]] to read a decimal value from.
|
987 | * @param predicate The given Predicate for which you want the decimal value.
|
988 | * @returns A decimal value for the given Predicate, if present, or null otherwise.
|
989 | */
|
990 | function getDecimalOne(thing, predicate) {
|
991 | const literalString = getLiteralOneOfType(thing, predicate, xmlSchemaTypes.decimal);
|
992 | if (literalString === null) {
|
993 | return null;
|
994 | }
|
995 | return deserializeDecimal(literalString);
|
996 | }
|
997 | /**
|
998 | * @param thing The [[Thing]] to read the decimal values from.
|
999 | * @param predicate The given Predicate for which you want the decimal values.
|
1000 | * @returns The decimal values for the given Predicate.
|
1001 | */
|
1002 | function getDecimalAll(thing, predicate) {
|
1003 | const literalStrings = getLiteralAllOfType(thing, predicate, xmlSchemaTypes.decimal);
|
1004 | return literalStrings
|
1005 | .map((literalString) => deserializeDecimal(literalString))
|
1006 | .filter((potentialDecimal) => potentialDecimal !== null);
|
1007 | }
|
1008 | /**
|
1009 | * @param thing The [[Thing]] to read an integer value from.
|
1010 | * @param predicate The given Predicate for which you want the integer value.
|
1011 | * @returns An integer value for the given Predicate, if present, or null otherwise.
|
1012 | */
|
1013 | function getIntegerOne(thing, predicate) {
|
1014 | const literalString = getLiteralOneOfType(thing, predicate, xmlSchemaTypes.integer);
|
1015 | if (literalString === null) {
|
1016 | return null;
|
1017 | }
|
1018 | return deserializeInteger(literalString);
|
1019 | }
|
1020 | /**
|
1021 | * @param thing The [[Thing]] to read the integer values from.
|
1022 | * @param predicate The given Predicate for which you want the integer values.
|
1023 | * @returns The integer values for the given Predicate.
|
1024 | */
|
1025 | function getIntegerAll(thing, predicate) {
|
1026 | const literalStrings = getLiteralAllOfType(thing, predicate, xmlSchemaTypes.integer);
|
1027 | return literalStrings
|
1028 | .map((literalString) => deserializeInteger(literalString))
|
1029 | .filter((potentialInteger) => potentialInteger !== null);
|
1030 | }
|
1031 | /**
|
1032 | * @param thing The [[Thing]] to read a localised string value from.
|
1033 | * @param predicate The given Predicate for which you want the localised string value.
|
1034 | * @param locale The desired locale for the string value.
|
1035 | * @returns A localised string value for the given Predicate, if present in `locale`, or null otherwise.
|
1036 | */
|
1037 | function getStringInLocaleOne(thing, predicate, locale) {
|
1038 | const localeStringMatcher = getLocaleStringMatcher(predicate, locale);
|
1039 | const matchingQuad = findOne(thing, localeStringMatcher);
|
1040 | if (matchingQuad === null) {
|
1041 | return null;
|
1042 | }
|
1043 | return matchingQuad.object.value;
|
1044 | }
|
1045 | /**
|
1046 | * @param thing The [[Thing]] to read the localised string values from.
|
1047 | * @param predicate The given Predicate for which you want the localised string values.
|
1048 | * @param locale The desired locale for the string values.
|
1049 | * @returns The localised string values for the given Predicate.
|
1050 | */
|
1051 | function getStringInLocaleAll(thing, predicate, locale) {
|
1052 | const localeStringMatcher = getLocaleStringMatcher(predicate, locale);
|
1053 | const matchingQuads = findAll(thing, localeStringMatcher);
|
1054 | return matchingQuads.map((quad) => quad.object.value);
|
1055 | }
|
1056 | /**
|
1057 | * @param thing The [[Thing]] to read a string value from.
|
1058 | * @param predicate The given Predicate for which you want the string value.
|
1059 | * @returns A string value for the given Predicate, if present, or null otherwise.
|
1060 | */
|
1061 | function getStringUnlocalizedOne(thing, predicate) {
|
1062 | const literalString = getLiteralOneOfType(thing, predicate, xmlSchemaTypes.string);
|
1063 | return literalString;
|
1064 | }
|
1065 | /**
|
1066 | * @param thing The [[Thing]] to read the string values from.
|
1067 | * @param predicate The given Predicate for which you want the string values.
|
1068 | * @returns The string values for the given Predicate.
|
1069 | */
|
1070 | function getStringUnlocalizedAll(thing, predicate) {
|
1071 | const literalStrings = getLiteralAllOfType(thing, predicate, xmlSchemaTypes.string);
|
1072 | return literalStrings;
|
1073 | }
|
1074 | /**
|
1075 | * @param thing The [[Thing]] to read a NamedNode value from.
|
1076 | * @param predicate The given Predicate for which you want the NamedNode value.
|
1077 | * @returns A NamedNode value for the given Predicate, if present, or null otherwise.
|
1078 | * @ignore This should not be needed due to the other get*One() functions. If you do find yourself needing it, please file a feature request for your use case.
|
1079 | */
|
1080 | function getNamedNodeOne(thing, predicate) {
|
1081 | const namedNodeMatcher = getNamedNodeMatcher(predicate);
|
1082 | const matchingQuad = findOne(thing, namedNodeMatcher);
|
1083 | if (matchingQuad === null) {
|
1084 | return null;
|
1085 | }
|
1086 | return matchingQuad.object;
|
1087 | }
|
1088 | /**
|
1089 | * @param thing The [[Thing]] to read the NamedNode values from.
|
1090 | * @param predicate The given Predicate for which you want the NamedNode values.
|
1091 | * @returns The NamedNode values for the given Predicate.
|
1092 | * @ignore This should not be needed due to the other get*One() functions. If you do find yourself needing it, please file a feature request for your use case.
|
1093 | */
|
1094 | function getNamedNodeAll(thing, predicate) {
|
1095 | const namedNodeMatcher = getNamedNodeMatcher(predicate);
|
1096 | const matchingQuads = findAll(thing, namedNodeMatcher);
|
1097 | return matchingQuads.map((quad) => quad.object);
|
1098 | }
|
1099 | /**
|
1100 | * @param thing The [[Thing]] to read a Literal value from.
|
1101 | * @param predicate The given Predicate for which you want the Literal value.
|
1102 | * @returns A Literal value for the given Predicate, if present, or null otherwise.
|
1103 | * @ignore This should not be needed due to the other get*One() functions. If you do find yourself needing it, please file a feature request for your use case.
|
1104 | */
|
1105 | function getLiteralOne(thing, predicate) {
|
1106 | const literalMatcher = getLiteralMatcher(predicate);
|
1107 | const matchingQuad = findOne(thing, literalMatcher);
|
1108 | if (matchingQuad === null) {
|
1109 | return null;
|
1110 | }
|
1111 | return matchingQuad.object;
|
1112 | }
|
1113 | /**
|
1114 | * @param thing The [[Thing]] to read the Literal values from.
|
1115 | * @param predicate The given Predicate for which you want the Literal values.
|
1116 | * @returns The Literal values for the given Predicate.
|
1117 | * @ignore This should not be needed due to the other get*All() functions. If you do find yourself needing it, please file a feature request for your use case.
|
1118 | */
|
1119 | function getLiteralAll(thing, predicate) {
|
1120 | const literalMatcher = getLiteralMatcher(predicate);
|
1121 | const matchingQuads = findAll(thing, literalMatcher);
|
1122 | return matchingQuads.map((quad) => quad.object);
|
1123 | }
|
1124 | /**
|
1125 | * @param thing The [[Thing]] to extract a Quad from.
|
1126 | * @param matcher Callback function that returns a boolean indicating whether a given Quad should be included.
|
1127 | * @returns First Quad in `thing` for which `matcher` returned true.
|
1128 | */
|
1129 | function findOne(thing, matcher) {
|
1130 | for (const quad of thing) {
|
1131 | if (matcher(quad)) {
|
1132 | return quad;
|
1133 | }
|
1134 | }
|
1135 | return null;
|
1136 | }
|
1137 | /**
|
1138 | * @param thing The [[Thing]] to extract Quads from.
|
1139 | * @param matcher Callback function that returns a boolean indicating whether a given Quad should be included.
|
1140 | * @returns All Quads in `thing` for which `matcher` returned true.
|
1141 | */
|
1142 | function findAll(thing, matcher) {
|
1143 | const matched = [];
|
1144 | for (const quad of thing) {
|
1145 | if (matcher(quad)) {
|
1146 | matched.push(quad);
|
1147 | }
|
1148 | }
|
1149 | return matched;
|
1150 | }
|
1151 | function getNamedNodeMatcher(predicate) {
|
1152 | const predicateNode = asNamedNode(predicate);
|
1153 | const matcher = function matcher(quad) {
|
1154 | return predicateNode.equals(quad.predicate) && isNamedNode(quad.object);
|
1155 | };
|
1156 | return matcher;
|
1157 | }
|
1158 | function getLiteralMatcher(predicate) {
|
1159 | const predicateNode = asNamedNode(predicate);
|
1160 | const matcher = function matcher(quad) {
|
1161 | return predicateNode.equals(quad.predicate) && isLiteral(quad.object);
|
1162 | };
|
1163 | return matcher;
|
1164 | }
|
1165 | function getLiteralOfTypeMatcher(predicate, datatype) {
|
1166 | const predicateNode = asNamedNode(predicate);
|
1167 | const matcher = function matcher(quad) {
|
1168 | return (predicateNode.equals(quad.predicate) &&
|
1169 | isLiteral(quad.object) &&
|
1170 | quad.object.datatype.value === datatype);
|
1171 | };
|
1172 | return matcher;
|
1173 | }
|
1174 | function getLocaleStringMatcher(predicate, locale) {
|
1175 | const predicateNode = asNamedNode(predicate);
|
1176 | const matcher = function matcher(quad) {
|
1177 | return (predicateNode.equals(quad.predicate) &&
|
1178 | isLiteral(quad.object) &&
|
1179 | quad.object.datatype.value === xmlSchemaTypes.langString &&
|
1180 | quad.object.language.toLowerCase() === locale.toLowerCase());
|
1181 | };
|
1182 | return matcher;
|
1183 | }
|
1184 | /**
|
1185 | * @param thing The [Thing]] to read a Literal of the given type from.
|
1186 | * @param predicate The given Predicate for which you want the Literal value.
|
1187 | * @param literalType Set type of the Literal data.
|
1188 | * @returns The stringified value for the given Predicate and type, if present, or null otherwise.
|
1189 | */
|
1190 | function getLiteralOneOfType(thing, predicate, literalType) {
|
1191 | const literalOfTypeMatcher = getLiteralOfTypeMatcher(predicate, literalType);
|
1192 | const matchingQuad = findOne(thing, literalOfTypeMatcher);
|
1193 | if (matchingQuad === null) {
|
1194 | return null;
|
1195 | }
|
1196 | return matchingQuad.object.value;
|
1197 | }
|
1198 | /**
|
1199 | * @param thing The [Thing]] to read the Literals of the given type from.
|
1200 | * @param predicate The given Predicate for which you want the Literal values.
|
1201 | * @param literalType Set type of the Literal data.
|
1202 | * @returns The stringified values for the given Predicate and type.
|
1203 | */
|
1204 | function getLiteralAllOfType(thing, predicate, literalType) {
|
1205 | const literalOfTypeMatcher = getLiteralOfTypeMatcher(predicate, literalType);
|
1206 | const matchingQuads = findAll(thing, literalOfTypeMatcher);
|
1207 | return matchingQuads.map((quad) => quad.object.value);
|
1208 | }
|
1209 |
|
1210 | /**
|
1211 | * Copyright 2020 Inrupt Inc.
|
1212 | *
|
1213 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
1214 | * of this software and associated documentation files (the "Software"), to deal in
|
1215 | * the Software without restriction, including without limitation the rights to use,
|
1216 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
1217 | * Software, and to permit persons to whom the Software is furnished to do so,
|
1218 | * subject to the following conditions:
|
1219 | *
|
1220 | * The above copyright notice and this permission notice shall be included in
|
1221 | * all copies or substantial portions of the Software.
|
1222 | *
|
1223 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
1224 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
1225 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
1226 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
1227 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
1228 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1229 | */
|
1230 | /** @internal */
|
1231 | function internal_fetchResourceAcl(dataset, options = defaultFetchOptions) {
|
1232 | return __awaiter(this, void 0, void 0, function* () {
|
1233 | if (!unstable_hasAccessibleAcl(dataset)) {
|
1234 | return null;
|
1235 | }
|
1236 | try {
|
1237 | const aclLitDataset = yield fetchLitDataset(dataset.datasetInfo.unstable_aclUrl, options);
|
1238 | return Object.assign(aclLitDataset, {
|
1239 | accessTo: dataset.datasetInfo.fetchedFrom,
|
1240 | });
|
1241 | }
|
1242 | catch (e) {
|
1243 | // Since a Solid server adds a `Link` header to an ACL even if that ACL does not exist,
|
1244 | // failure to fetch the ACL is expected to happen - we just return `null` and let callers deal
|
1245 | // with it.
|
1246 | return null;
|
1247 | }
|
1248 | });
|
1249 | }
|
1250 | /** @internal */
|
1251 | function internal_fetchFallbackAcl(dataset, options = defaultFetchOptions) {
|
1252 | return __awaiter(this, void 0, void 0, function* () {
|
1253 | const resourceUrl = new URL(dataset.datasetInfo.fetchedFrom);
|
1254 | const resourcePath = resourceUrl.pathname;
|
1255 | // Note: we're currently assuming that the Origin is the root of the Pod. However, it is not yet
|
1256 | // set in stone that that will always be the case. We might need to check the Container's
|
1257 | // metadata at some point in time to check whether it is actually the root of the Pod.
|
1258 | // See: https://github.com/solid/specification/issues/153#issuecomment-624630022
|
1259 | if (resourcePath === "/") {
|
1260 | // We're already at the root, so there's no Container we can retrieve:
|
1261 | return null;
|
1262 | }
|
1263 | const containerPath = getContainerPath(resourcePath);
|
1264 | const containerIri = new URL(containerPath, resourceUrl.origin).href;
|
1265 | const containerInfo = yield internal_fetchLitDatasetInfo(containerIri, options);
|
1266 | if (!unstable_hasAccessibleAcl(containerInfo)) {
|
1267 | // If the current user does not have access to this Container's ACL,
|
1268 | // we cannot determine whether its ACL is the one that applies. Thus, return null:
|
1269 | return null;
|
1270 | }
|
1271 | const containerAcl = yield internal_fetchResourceAcl(containerInfo, options);
|
1272 | if (containerAcl === null) {
|
1273 | return internal_fetchFallbackAcl(containerInfo, options);
|
1274 | }
|
1275 | return containerAcl;
|
1276 | });
|
1277 | }
|
1278 | function getContainerPath(resourcePath) {
|
1279 | const resourcePathWithoutTrailingSlash = resourcePath.substring(resourcePath.length - 1) === "/"
|
1280 | ? resourcePath.substring(0, resourcePath.length - 1)
|
1281 | : resourcePath;
|
1282 | const containerPath = resourcePath.substring(0, resourcePathWithoutTrailingSlash.lastIndexOf("/")) + "/";
|
1283 | return containerPath;
|
1284 | }
|
1285 | /**
|
1286 | * Verify whether an ACL was found for the given LitDataset.
|
1287 | *
|
1288 | * A LitDataset fetched with [[unstable_fetchLitDatasetWithAcl]] _might_ have an ACL attached, but
|
1289 | * we cannot be sure: it might be that none exists for this specific Resource (in which case the
|
1290 | * fallback ACL applies), or the currently authenticated user (if any) might not have Control access
|
1291 | * to the fetched Resource.
|
1292 | *
|
1293 | * This function verifies that the LitDataset's ACL is accessible.
|
1294 | *
|
1295 | * @param dataset A [[LitDataset]] that might have an ACL attached.
|
1296 | * @returns Whether `dataset` has an ACL attached.
|
1297 | */
|
1298 | function unstable_hasResourceAcl(dataset) {
|
1299 | return typeof dataset.acl.resourceAcl !== "undefined";
|
1300 | }
|
1301 | function unstable_getResourceAcl(dataset) {
|
1302 | if (!unstable_hasResourceAcl(dataset)) {
|
1303 | return null;
|
1304 | }
|
1305 | return dataset.acl.resourceAcl;
|
1306 | }
|
1307 | /**
|
1308 | * Verify whether a fallback ACL was found for the given LitDataset.
|
1309 | *
|
1310 | * A LitDataset fetched with [[unstable_fetchLitDatasetWithAcl]] _might_ have a fallback ACL
|
1311 | * attached, but we cannot be sure: the currently authenticated user (if any) might not have Control
|
1312 | * access to one of the fetched Resource's Containers.
|
1313 | *
|
1314 | * This function verifies that the fallback ACL is accessible.
|
1315 | *
|
1316 | * @param dataset A [[LitDataset]] that might have a fallback ACL attached.
|
1317 | * @returns Whether `dataset` has a fallback ACL attached.
|
1318 | */
|
1319 | function unstable_hasFallbackAcl(dataset) {
|
1320 | return dataset.acl.fallbackAcl !== null;
|
1321 | }
|
1322 | function unstable_getFallbackAcl(dataset) {
|
1323 | if (!unstable_hasFallbackAcl(dataset)) {
|
1324 | return null;
|
1325 | }
|
1326 | return dataset.acl.fallbackAcl;
|
1327 | }
|
1328 | /** @internal */
|
1329 | function internal_getAclRules(aclDataset) {
|
1330 | const things = getThingAll(aclDataset);
|
1331 | return things.filter(isAclRule);
|
1332 | }
|
1333 | function isAclRule(thing) {
|
1334 | return getIriAll(thing, rdf.type).includes(acl.Authorization);
|
1335 | }
|
1336 | /** @internal */
|
1337 | function internal_getResourceAclRulesForResource(aclRules, resource) {
|
1338 | return aclRules.filter((rule) => appliesToResource(rule, resource));
|
1339 | }
|
1340 | function appliesToResource(aclRule, resource) {
|
1341 | return getIriAll(aclRule, acl.accessTo).includes(resource);
|
1342 | }
|
1343 | /** @internal */
|
1344 | function internal_getDefaultAclRulesForResource(aclRules, resource) {
|
1345 | return aclRules.filter((rule) => isDefaultForResource(rule, resource));
|
1346 | }
|
1347 | function isDefaultForResource(aclRule, resource) {
|
1348 | return getIriAll(aclRule, acl.default).includes(resource);
|
1349 | }
|
1350 | /** @internal */
|
1351 | function internal_getAccessModes(rule) {
|
1352 | const ruleAccessModes = getIriAll(rule, acl.mode);
|
1353 | const writeAccess = ruleAccessModes.includes(accessModeIriStrings.write);
|
1354 | return writeAccess
|
1355 | ? {
|
1356 | read: ruleAccessModes.includes(accessModeIriStrings.read),
|
1357 | append: true,
|
1358 | write: true,
|
1359 | control: ruleAccessModes.includes(accessModeIriStrings.control),
|
1360 | }
|
1361 | : {
|
1362 | read: ruleAccessModes.includes(accessModeIriStrings.read),
|
1363 | append: ruleAccessModes.includes(accessModeIriStrings.append),
|
1364 | write: false,
|
1365 | control: ruleAccessModes.includes(accessModeIriStrings.control),
|
1366 | };
|
1367 | }
|
1368 | /** @internal */
|
1369 | function internal_combineAccessModes(modes) {
|
1370 | return modes.reduce((accumulator, current) => {
|
1371 | const writeAccess = accumulator.write || current.write;
|
1372 | return writeAccess
|
1373 | ? {
|
1374 | read: accumulator.read || current.read,
|
1375 | append: true,
|
1376 | write: true,
|
1377 | control: accumulator.control || current.control,
|
1378 | }
|
1379 | : {
|
1380 | read: accumulator.read || current.read,
|
1381 | append: accumulator.append || current.append,
|
1382 | write: false,
|
1383 | control: accumulator.control || current.control,
|
1384 | };
|
1385 | }, { read: false, append: false, write: false, control: false });
|
1386 | }
|
1387 | /**
|
1388 | * IRIs of potential Access Modes
|
1389 | * @internal
|
1390 | */
|
1391 | const accessModeIriStrings = {
|
1392 | read: "http://www.w3.org/ns/auth/acl#Read",
|
1393 | append: "http://www.w3.org/ns/auth/acl#Append",
|
1394 | write: "http://www.w3.org/ns/auth/acl#Write",
|
1395 | control: "http://www.w3.org/ns/auth/acl#Control",
|
1396 | };
|
1397 |
|
1398 | /**
|
1399 | * Copyright 2020 Inrupt Inc.
|
1400 | *
|
1401 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
1402 | * of this software and associated documentation files (the "Software"), to deal in
|
1403 | * the Software without restriction, including without limitation the rights to use,
|
1404 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
1405 | * Software, and to permit persons to whom the Software is furnished to do so,
|
1406 | * subject to the following conditions:
|
1407 | *
|
1408 | * The above copyright notice and this permission notice shall be included in
|
1409 | * all copies or substantial portions of the Software.
|
1410 | *
|
1411 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
1412 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
1413 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
1414 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
1415 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
1416 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1417 | */
|
1418 | /**
|
1419 | * Initialise a new [[LitDataset]] in memory.
|
1420 | *
|
1421 | * @returns An empty [[LitDataset]].
|
1422 | */
|
1423 | function createLitDataset() {
|
1424 | return dataset();
|
1425 | }
|
1426 | /**
|
1427 | * @internal
|
1428 | */
|
1429 | const defaultFetchOptions = {
|
1430 | fetch: fetch,
|
1431 | };
|
1432 | /**
|
1433 | * Fetch a LitDataset from the given URL. Currently requires the LitDataset to be available as [Turtle](https://www.w3.org/TR/turtle/).
|
1434 | *
|
1435 | * @param url URL to fetch a [[LitDataset]] from.
|
1436 | * @param options Optional parameter `options.fetch`: An alternative `fetch` function to make the HTTP request, compatible with the browser-native [fetch API](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters).
|
1437 | * @returns Promise resolving to a [[LitDataset]] containing the data at the given Resource, or rejecting if fetching it failed.
|
1438 | */
|
1439 | function fetchLitDataset(url, options = defaultFetchOptions) {
|
1440 | return __awaiter(this, void 0, void 0, function* () {
|
1441 | const config = Object.assign(Object.assign({}, defaultFetchOptions), options);
|
1442 | const response = yield config.fetch(url);
|
1443 | if (!response.ok) {
|
1444 | throw new Error(`Fetching the Resource failed: ${response.status} ${response.statusText}.`);
|
1445 | }
|
1446 | const data = yield response.text();
|
1447 | const triples = yield turtleToTriples(data, url);
|
1448 | const resource = dataset();
|
1449 | triples.forEach((triple) => resource.add(triple));
|
1450 | const datasetInfo = parseDatasetInfo(response);
|
1451 | const resourceWithDatasetInfo = Object.assign(resource, { datasetInfo: datasetInfo });
|
1452 | return resourceWithDatasetInfo;
|
1453 | });
|
1454 | }
|
1455 | /**
|
1456 | * @internal
|
1457 | */
|
1458 | function internal_fetchLitDatasetInfo(url, options = defaultFetchOptions) {
|
1459 | return __awaiter(this, void 0, void 0, function* () {
|
1460 | const config = Object.assign(Object.assign({}, defaultFetchOptions), options);
|
1461 | const response = yield config.fetch(url, { method: "HEAD" });
|
1462 | if (!response.ok) {
|
1463 | throw new Error(`Fetching the Resource metadata failed: ${response.status} ${response.statusText}.`);
|
1464 | }
|
1465 | const datasetInfo = parseDatasetInfo(response);
|
1466 | return { datasetInfo: datasetInfo };
|
1467 | });
|
1468 | }
|
1469 | function parseDatasetInfo(response) {
|
1470 | const datasetInfo = {
|
1471 | fetchedFrom: response.url,
|
1472 | };
|
1473 | const linkHeader = response.headers.get("Link");
|
1474 | if (linkHeader) {
|
1475 | const parsedLinks = LinkHeader.parse(linkHeader);
|
1476 | const aclLinks = parsedLinks.get("rel", "acl");
|
1477 | if (aclLinks.length === 1) {
|
1478 | datasetInfo.unstable_aclUrl = new URL(aclLinks[0].uri, datasetInfo.fetchedFrom).href;
|
1479 | }
|
1480 | }
|
1481 | const wacAllowHeader = response.headers.get("WAC-Allow");
|
1482 | if (wacAllowHeader) {
|
1483 | datasetInfo.unstable_permissions = parseWacAllowHeader(wacAllowHeader);
|
1484 | }
|
1485 | return datasetInfo;
|
1486 | }
|
1487 | /**
|
1488 | * Experimental: fetch a LitDataset and its associated Access Control List.
|
1489 | *
|
1490 | * This is an experimental function that fetches both a Resource, the linked ACL Resource (if
|
1491 | * available), and the ACL that applies to it if the linked ACL Resource is not available. This can
|
1492 | * result in many HTTP requests being executed, in lieu of the Solid spec mandating servers to
|
1493 | * provide this info in a single request. Therefore, and because this function is still
|
1494 | * experimental, prefer [[fetchLitDataset]] instead.
|
1495 | *
|
1496 | * If the Resource does not advertise the ACL Resource (because the authenticated user does not have
|
1497 | * access to it), the `acl` property in the returned value will be null. `acl.resourceAcl` will be
|
1498 | * undefined if the Resource's linked ACL Resource could not be fetched (because it does not exist),
|
1499 | * and `acl.fallbackAcl` will be null if the applicable Container's ACL is not accessible to the
|
1500 | * authenticated user.
|
1501 | *
|
1502 | * @param url URL of the LitDataset to fetch.
|
1503 | * @param options Optional parameter `options.fetch`: An alternative `fetch` function to make the HTTP request, compatible with the browser-native [fetch API](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters).
|
1504 | * @returns A LitDataset and the ACLs that apply to it, if available to the authenticated user.
|
1505 | */
|
1506 | function unstable_fetchLitDatasetWithAcl(url, options = defaultFetchOptions) {
|
1507 | return __awaiter(this, void 0, void 0, function* () {
|
1508 | const litDataset = yield fetchLitDataset(url, options);
|
1509 | if (!unstable_hasAccessibleAcl(litDataset)) {
|
1510 | return Object.assign(litDataset, { acl: null });
|
1511 | }
|
1512 | const [resourceAcl, fallbackAcl] = yield Promise.all([
|
1513 | internal_fetchResourceAcl(litDataset, options),
|
1514 | internal_fetchFallbackAcl(litDataset, options),
|
1515 | ]);
|
1516 | const acl = {
|
1517 | fallbackAcl: fallbackAcl,
|
1518 | resourceAcl: resourceAcl !== null ? resourceAcl : undefined,
|
1519 | };
|
1520 | return Object.assign(litDataset, { acl: acl });
|
1521 | });
|
1522 | }
|
1523 | const defaultSaveOptions = {
|
1524 | fetch: fetch,
|
1525 | };
|
1526 | /**
|
1527 | * Given a LitDataset, store it in a Solid Pod (overwriting the existing data at the given URL).
|
1528 | *
|
1529 | * @param url URL to save `litDataset` to.
|
1530 | * @param litDataset The [[LitDataset]] to save.
|
1531 | * @param options Optional parameter `options.fetch`: An alternative `fetch` function to make the HTTP request, compatible with the browser-native [fetch API](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters).
|
1532 | * @returns A Promise resolving to a [[LitDataset]] containing the stored data, or rejecting if saving it failed.
|
1533 | */
|
1534 | function saveLitDatasetAt(url, litDataset, options = defaultSaveOptions) {
|
1535 | return __awaiter(this, void 0, void 0, function* () {
|
1536 | const config = Object.assign(Object.assign({}, defaultSaveOptions), options);
|
1537 | let requestInit;
|
1538 | if (isUpdate(litDataset, url)) {
|
1539 | const deleteStatement = litDataset.changeLog.deletions.length > 0
|
1540 | ? `DELETE DATA {${(yield triplesToTurtle(litDataset.changeLog.deletions.map(getNamedNodesForLocalNodes))).trim()}};`
|
1541 | : "";
|
1542 | const insertStatement = litDataset.changeLog.additions.length > 0
|
1543 | ? `INSERT DATA {${(yield triplesToTurtle(litDataset.changeLog.additions.map(getNamedNodesForLocalNodes))).trim()}};`
|
1544 | : "";
|
1545 | requestInit = {
|
1546 | method: "PATCH",
|
1547 | body: `${deleteStatement} ${insertStatement}`,
|
1548 | headers: {
|
1549 | "Content-Type": "application/sparql-update",
|
1550 | },
|
1551 | };
|
1552 | }
|
1553 | else {
|
1554 | requestInit = {
|
1555 | method: "PUT",
|
1556 | body: yield triplesToTurtle(Array.from(litDataset).map(getNamedNodesForLocalNodes)),
|
1557 | headers: {
|
1558 | "Content-Type": "text/turtle",
|
1559 | "If-None-Match": "*",
|
1560 | Link: '<http://www.w3.org/ns/ldp#Resource>; rel="type"',
|
1561 | },
|
1562 | };
|
1563 | }
|
1564 | const response = yield config.fetch(url, requestInit);
|
1565 | if (!response.ok) {
|
1566 | throw new Error(`Storing the Resource failed: ${response.status} ${response.statusText}.`);
|
1567 | }
|
1568 | const datasetInfo = hasDatasetInfo(litDataset)
|
1569 | ? Object.assign(Object.assign({}, litDataset.datasetInfo), { fetchedFrom: url }) : { fetchedFrom: url };
|
1570 | const storedDataset = Object.assign(litDataset, {
|
1571 | changeLog: { additions: [], deletions: [] },
|
1572 | datasetInfo: datasetInfo,
|
1573 | });
|
1574 | const storedDatasetWithResolvedIris = resolveLocalIrisInLitDataset(storedDataset);
|
1575 | return storedDatasetWithResolvedIris;
|
1576 | });
|
1577 | }
|
1578 | function isUpdate(litDataset, url) {
|
1579 | return (hasChangelog(litDataset) &&
|
1580 | hasDatasetInfo(litDataset) &&
|
1581 | typeof litDataset.datasetInfo.fetchedFrom === "string" &&
|
1582 | litDataset.datasetInfo.fetchedFrom === url);
|
1583 | }
|
1584 | const defaultSaveInContainerOptions = {
|
1585 | fetch: fetch,
|
1586 | };
|
1587 | /**
|
1588 | * Given a LitDataset, store it in a Solid Pod in a new Resource inside a Container.
|
1589 | *
|
1590 | * @param containerUrl URL of the Container in which to create a new Resource.
|
1591 | * @param litDataset The [[LitDataset]] to save to a new Resource in the given Container.
|
1592 | * @param options Optional parameter `options.fetch`: An alternative `fetch` function to make the HTTP request, compatible with the browser-native [fetch API](https://developer.mozilla.org/docs/Web/API/WindowOrWorkerGlobalScope/fetch#parameters).
|
1593 | * @returns A Promise resolving to a [[LitDataset]] containing the stored data linked to the new Resource, or rejecting if saving it failed.
|
1594 | */
|
1595 | function saveLitDatasetInContainer(containerUrl, litDataset, options = defaultSaveInContainerOptions) {
|
1596 | return __awaiter(this, void 0, void 0, function* () {
|
1597 | const config = Object.assign(Object.assign({}, defaultSaveOptions), options);
|
1598 | const rawTurtle = yield triplesToTurtle(Array.from(litDataset).map(getNamedNodesForLocalNodes));
|
1599 | const headers = {
|
1600 | "Content-Type": "text/turtle",
|
1601 | Link: '<http://www.w3.org/ns/ldp#Resource>; rel="type"',
|
1602 | };
|
1603 | if (options.slugSuggestion) {
|
1604 | headers.slug = options.slugSuggestion;
|
1605 | }
|
1606 | const response = yield config.fetch(containerUrl, {
|
1607 | method: "POST",
|
1608 | body: rawTurtle,
|
1609 | headers: headers,
|
1610 | });
|
1611 | if (!response.ok) {
|
1612 | throw new Error(`Storing the Resource in the Container failed: ${response.status} ${response.statusText}.`);
|
1613 | }
|
1614 | const locationHeader = response.headers.get("Location");
|
1615 | if (locationHeader === null) {
|
1616 | throw new Error("Could not determine the location for the newly saved LitDataset.");
|
1617 | }
|
1618 | const resourceIri = new URL(locationHeader, new URL(containerUrl).origin)
|
1619 | .href;
|
1620 | const datasetInfo = {
|
1621 | fetchedFrom: resourceIri,
|
1622 | };
|
1623 | const resourceWithDatasetInfo = Object.assign(litDataset, { datasetInfo: datasetInfo });
|
1624 | const resourceWithResolvedIris = resolveLocalIrisInLitDataset(resourceWithDatasetInfo);
|
1625 | return resourceWithResolvedIris;
|
1626 | });
|
1627 | }
|
1628 | function getNamedNodesForLocalNodes(quad) {
|
1629 | const subject = isLocalNode(quad.subject)
|
1630 | ? getNamedNodeFromLocalNode(quad.subject)
|
1631 | : quad.subject;
|
1632 | const object = isLocalNode(quad.object)
|
1633 | ? getNamedNodeFromLocalNode(quad.object)
|
1634 | : quad.object;
|
1635 | return Object.assign(Object.assign({}, quad), { subject: subject, object: object });
|
1636 | }
|
1637 | function getNamedNodeFromLocalNode(localNode) {
|
1638 | return DataFactory.namedNode("#" + localNode.name);
|
1639 | }
|
1640 | function resolveLocalIrisInLitDataset(litDataset) {
|
1641 | const resourceIri = litDataset.datasetInfo.fetchedFrom;
|
1642 | const unresolvedQuads = Array.from(litDataset);
|
1643 | unresolvedQuads.forEach((unresolvedQuad) => {
|
1644 | const resolvedQuad = resolveIriForLocalNodes(unresolvedQuad, resourceIri);
|
1645 | litDataset.delete(unresolvedQuad);
|
1646 | litDataset.add(resolvedQuad);
|
1647 | });
|
1648 | return litDataset;
|
1649 | }
|
1650 | /**
|
1651 | * Parse a WAC-Allow header into user and public access booleans.
|
1652 | *
|
1653 | * @param wacAllowHeader A WAC-Allow header in the format `user="read append write control",public="read"`
|
1654 | * @see https://github.com/solid/solid-spec/blob/cb1373a369398d561b909009bd0e5a8c3fec953b/api-rest.md#wac-allow-headers
|
1655 | */
|
1656 | function parseWacAllowHeader(wacAllowHeader) {
|
1657 | function parsePermissionStatement(permissionStatement) {
|
1658 | const permissions = permissionStatement.split(" ");
|
1659 | const writePermission = permissions.includes("write");
|
1660 | return writePermission
|
1661 | ? {
|
1662 | read: permissions.includes("read"),
|
1663 | append: true,
|
1664 | write: true,
|
1665 | control: permissions.includes("control"),
|
1666 | }
|
1667 | : {
|
1668 | read: permissions.includes("read"),
|
1669 | append: permissions.includes("append"),
|
1670 | write: false,
|
1671 | control: permissions.includes("control"),
|
1672 | };
|
1673 | }
|
1674 | function getStatementFor(header, scope) {
|
1675 | const relevantEntries = header
|
1676 | .split(",")
|
1677 | .map((rawEntry) => rawEntry.split("="))
|
1678 | .filter((parts) => parts.length === 2 && parts[0].trim() === scope);
|
1679 | // There should only be one statement with the given scope:
|
1680 | if (relevantEntries.length !== 1) {
|
1681 | return "";
|
1682 | }
|
1683 | const relevantStatement = relevantEntries[0][1].trim();
|
1684 | // The given statement should be wrapped in double quotes to be valid:
|
1685 | if (relevantStatement.charAt(0) !== '"' ||
|
1686 | relevantStatement.charAt(relevantStatement.length - 1) !== '"') {
|
1687 | return "";
|
1688 | }
|
1689 | // Return the statment without the wrapping quotes, e.g.: read append write control
|
1690 | return relevantStatement.substring(1, relevantStatement.length - 1);
|
1691 | }
|
1692 | return {
|
1693 | user: parsePermissionStatement(getStatementFor(wacAllowHeader, "user")),
|
1694 | public: parsePermissionStatement(getStatementFor(wacAllowHeader, "public")),
|
1695 | };
|
1696 | }
|
1697 |
|
1698 | /**
|
1699 | * Copyright 2020 Inrupt Inc.
|
1700 | *
|
1701 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
1702 | * of this software and associated documentation files (the "Software"), to deal in
|
1703 | * the Software without restriction, including without limitation the rights to use,
|
1704 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
1705 | * Software, and to permit persons to whom the Software is furnished to do so,
|
1706 | * subject to the following conditions:
|
1707 | *
|
1708 | * The above copyright notice and this permission notice shall be included in
|
1709 | * all copies or substantial portions of the Software.
|
1710 | *
|
1711 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
1712 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
1713 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
1714 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
1715 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
1716 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1717 | */
|
1718 | /**
|
1719 | * Create a new Thing with a URL added for a Predicate.
|
1720 | *
|
1721 | * This preserves existing values for the given Predicate. To replace them, see [[setUrl]].
|
1722 | *
|
1723 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1724 | *
|
1725 | * @param thing Thing to add a URL value to.
|
1726 | * @param predicate Predicate for which to add the given URL value.
|
1727 | * @param url URL to add to `thing` for the given `predicate`.
|
1728 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1729 | */
|
1730 | const addUrl = (thing, predicate, url) => {
|
1731 | const predicateNode = asNamedNode(predicate);
|
1732 | const newThing = cloneThing(thing);
|
1733 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, toNode(url)));
|
1734 | return newThing;
|
1735 | };
|
1736 | /** @hidden Alias for [[addUrl]] for those who prefer IRI terminology. */
|
1737 | const addIri = addUrl;
|
1738 | /**
|
1739 | * Create a new Thing with a boolean added for a Predicate.
|
1740 | *
|
1741 | * This preserves existing values for the given Predicate. To replace them, see [[setBoolean]].
|
1742 | *
|
1743 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1744 | *
|
1745 | * @param thing Thing to add a boolean value to.
|
1746 | * @param predicate Predicate for which to add the given boolean value.
|
1747 | * @param value Boolean to add to `thing` for the given `predicate`.
|
1748 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1749 | */
|
1750 | const addBoolean = (thing, predicate, value) => {
|
1751 | return addLiteralOfType(thing, predicate, serializeBoolean(value), xmlSchemaTypes.boolean);
|
1752 | };
|
1753 | /**
|
1754 | * Create a new Thing with a datetime added for a Predicate.
|
1755 | *
|
1756 | * This preserves existing values for the given Predicate. To replace them, see [[setDatetime]].
|
1757 | *
|
1758 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1759 | *
|
1760 | * @param thing Thing to add a datetime value to.
|
1761 | * @param predicate Predicate for which to add the given datetime value.
|
1762 | * @param value Datetime to add to `thing` for the given `predicate`.
|
1763 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1764 | */
|
1765 | const addDatetime = (thing, predicate, value) => {
|
1766 | return addLiteralOfType(thing, predicate, serializeDatetime(value), xmlSchemaTypes.dateTime);
|
1767 | };
|
1768 | /**
|
1769 | * Create a new Thing with a decimal added for a Predicate.
|
1770 | *
|
1771 | * This preserves existing values for the given Predicate. To replace them, see [[setDecimal]].
|
1772 | *
|
1773 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1774 | *
|
1775 | * @param thing Thing to add a decimal value to.
|
1776 | * @param predicate Predicate for which to add the given decimal value.
|
1777 | * @param value Decimal to add to `thing` for the given `predicate`.
|
1778 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1779 | */
|
1780 | const addDecimal = (thing, predicate, value) => {
|
1781 | return addLiteralOfType(thing, predicate, serializeDecimal(value), xmlSchemaTypes.decimal);
|
1782 | };
|
1783 | /**
|
1784 | * Create a new Thing with an integer added for a Predicate.
|
1785 | *
|
1786 | * This preserves existing values for the given Predicate. To replace them, see [[setInteger]].
|
1787 | *
|
1788 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1789 | *
|
1790 | * @param thing Thing to add an integer value to.
|
1791 | * @param predicate Predicate for which to add the given integer value.
|
1792 | * @param value Integer to add to `thing` for the given `predicate`.
|
1793 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1794 | */
|
1795 | const addInteger = (thing, predicate, value) => {
|
1796 | return addLiteralOfType(thing, predicate, serializeInteger(value), xmlSchemaTypes.integer);
|
1797 | };
|
1798 | function addStringInLocale(thing, predicate, value, locale) {
|
1799 | const literal = DataFactory.literal(value, normalizeLocale(locale));
|
1800 | return addLiteral(thing, predicate, literal);
|
1801 | }
|
1802 | /**
|
1803 | * Create a new Thing with an unlocalised string added for a Predicate.
|
1804 | *
|
1805 | * This preserves existing values for the given Predicate. To replace them, see [[setStringUnlocalized]].
|
1806 | *
|
1807 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1808 | *
|
1809 | * @param thing Thing to add an unlocalised string value to.
|
1810 | * @param predicate Predicate for which to add the given string value.
|
1811 | * @param value String to add to `thing` for the given `predicate`.
|
1812 | * @returns A new Thing equal to the input Thing with the given value added for the given Predicate.
|
1813 | */
|
1814 | const addStringUnlocalized = (thing, predicate, value) => {
|
1815 | return addLiteralOfType(thing, predicate, value, xmlSchemaTypes.string);
|
1816 | };
|
1817 | function addNamedNode(thing, predicate, value) {
|
1818 | const predicateNode = asNamedNode(predicate);
|
1819 | const newThing = cloneThing(thing);
|
1820 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, value));
|
1821 | return newThing;
|
1822 | }
|
1823 | function addLiteral(thing, predicate, value) {
|
1824 | const predicateNode = asNamedNode(predicate);
|
1825 | const newThing = cloneThing(thing);
|
1826 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, value));
|
1827 | return newThing;
|
1828 | }
|
1829 | function addLiteralOfType(thing, predicate, value, type) {
|
1830 | const literal = DataFactory.literal(value, type);
|
1831 | return addLiteral(thing, predicate, literal);
|
1832 | }
|
1833 |
|
1834 | /**
|
1835 | * Copyright 2020 Inrupt Inc.
|
1836 | *
|
1837 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
1838 | * of this software and associated documentation files (the "Software"), to deal in
|
1839 | * the Software without restriction, including without limitation the rights to use,
|
1840 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
1841 | * Software, and to permit persons to whom the Software is furnished to do so,
|
1842 | * subject to the following conditions:
|
1843 | *
|
1844 | * The above copyright notice and this permission notice shall be included in
|
1845 | * all copies or substantial portions of the Software.
|
1846 | *
|
1847 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
1848 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
1849 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
1850 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
1851 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
1852 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1853 | */
|
1854 | function removeAll(thing, predicate) {
|
1855 | const predicateNode = asNamedNode(predicate);
|
1856 | const updatedThing = filterThing(thing, (quad) => !quad.predicate.equals(predicateNode));
|
1857 | return updatedThing;
|
1858 | }
|
1859 | /**
|
1860 | * Create a new Thing with the given URL removed for the given Predicate.
|
1861 | *
|
1862 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1863 | *
|
1864 | * @param thing Thing to remove a URL value from.
|
1865 | * @param predicate Predicate for which to remove the given URL value.
|
1866 | * @param value URL to remove from `thing` for the given `predicate`.
|
1867 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1868 | */
|
1869 | const removeUrl = (thing, predicate, value) => {
|
1870 | const predicateNode = asNamedNode(predicate);
|
1871 | const iriNode = isNamedNode(value)
|
1872 | ? value
|
1873 | : typeof value === "string"
|
1874 | ? asNamedNode(value)
|
1875 | : asNamedNode(asIri(value));
|
1876 | const updatedThing = filterThing(thing, (quad) => {
|
1877 | return (!quad.predicate.equals(predicateNode) ||
|
1878 | !isNamedNode(quad.object) ||
|
1879 | !quad.object.equals(iriNode));
|
1880 | });
|
1881 | return updatedThing;
|
1882 | };
|
1883 | /** @hidden Alias of [[removeUrl]] for those who prefer IRI terminology. */
|
1884 | const removeIri = removeUrl;
|
1885 | /**
|
1886 | * Create a new Thing with the given boolean removed for the given Predicate.
|
1887 | *
|
1888 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1889 | *
|
1890 | * @param thing Thing to remove a boolean value from.
|
1891 | * @param predicate Predicate for which to remove the given boolean value.
|
1892 | * @param value Boolean to remove from `thing` for the given `predicate`.
|
1893 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1894 | */
|
1895 | const removeBoolean = (thing, predicate, value) => {
|
1896 | return removeLiteralOfType(thing, predicate, serializeBoolean(value), xmlSchemaTypes.boolean);
|
1897 | };
|
1898 | /**
|
1899 | * Create a new Thing with the given datetime removed for the given Predicate.
|
1900 | *
|
1901 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1902 | *
|
1903 | * @param thing Thing to remove a datetime value from.
|
1904 | * @param predicate Predicate for which to remove the given datetime value.
|
1905 | * @param value Datetime to remove from `thing` for the given `predicate`.
|
1906 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1907 | */
|
1908 | const removeDatetime = (thing, predicate, value) => {
|
1909 | return removeLiteralOfType(thing, predicate, serializeDatetime(value), xmlSchemaTypes.dateTime);
|
1910 | };
|
1911 | /**
|
1912 | * Create a new Thing with the given decimal removed for the given Predicate.
|
1913 | *
|
1914 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1915 | *
|
1916 | * @param thing Thing to remove a decimal value from.
|
1917 | * @param predicate Predicate for which to remove the given decimal value.
|
1918 | * @param value Decimal to remove from `thing` for the given `predicate`.
|
1919 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1920 | */
|
1921 | const removeDecimal = (thing, predicate, value) => {
|
1922 | return removeLiteralOfType(thing, predicate, serializeDecimal(value), xmlSchemaTypes.decimal);
|
1923 | };
|
1924 | /**
|
1925 | * Create a new Thing with the given integer removed for the given Predicate.
|
1926 | *
|
1927 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1928 | *
|
1929 | * @param thing Thing to remove an integer value from.
|
1930 | * @param predicate Predicate for which to remove the given integer value.
|
1931 | * @param value Integer to remove from `thing` for the given `predicate`.
|
1932 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1933 | */
|
1934 | const removeInteger = (thing, predicate, value) => {
|
1935 | return removeLiteralOfType(thing, predicate, serializeInteger(value), xmlSchemaTypes.integer);
|
1936 | };
|
1937 | function removeStringInLocale(thing, predicate, value, locale) {
|
1938 | // Note: Due to how the `DataFactory.literal` constructor behaves, this function
|
1939 | // must call directly `removeLiteral` directly, with the locale as the data
|
1940 | // type of the Literal (which is not a valid NamedNode).
|
1941 | return removeLiteral(thing, predicate, DataFactory.literal(value, normalizeLocale(locale)));
|
1942 | }
|
1943 | /**
|
1944 | * Create a new Thing with the given unlocalised string removed for the given Predicate.
|
1945 | *
|
1946 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
1947 | *
|
1948 | * @param thing Thing to remove an unlocalised string value from.
|
1949 | * @param predicate Predicate for which to remove the given string value.
|
1950 | * @param value String to remove from `thing` for the given `predicate`.
|
1951 | * @returns A new Thing equal to the input Thing with the given value removed for the given Predicate.
|
1952 | */
|
1953 | const removeStringUnlocalized = (thing, predicate, value) => {
|
1954 | return removeLiteralOfType(thing, predicate, value, xmlSchemaTypes.string);
|
1955 | };
|
1956 | function removeNamedNode(thing, predicate, value) {
|
1957 | const predicateNode = asNamedNode(predicate);
|
1958 | const updatedThing = filterThing(thing, (quad) => {
|
1959 | return (!quad.predicate.equals(predicateNode) ||
|
1960 | !isNamedNode(quad.object) ||
|
1961 | !quad.object.equals(value));
|
1962 | });
|
1963 | return updatedThing;
|
1964 | }
|
1965 | function removeLiteral(thing, predicate, value) {
|
1966 | const predicateNode = asNamedNode(predicate);
|
1967 | const updatedThing = filterThing(thing, (quad) => {
|
1968 | return (!quad.predicate.equals(predicateNode) ||
|
1969 | !isLiteral(quad.object) ||
|
1970 | !quad.object.equals(value));
|
1971 | });
|
1972 | return updatedThing;
|
1973 | }
|
1974 | function removeLiteralOfType(thing, predicate, value, type) {
|
1975 | const updatedThing = removeLiteral(thing, predicate, DataFactory.literal(value, DataFactory.namedNode(type)));
|
1976 | return updatedThing;
|
1977 | }
|
1978 |
|
1979 | /**
|
1980 | * Copyright 2020 Inrupt Inc.
|
1981 | *
|
1982 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
1983 | * of this software and associated documentation files (the "Software"), to deal in
|
1984 | * the Software without restriction, including without limitation the rights to use,
|
1985 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
1986 | * Software, and to permit persons to whom the Software is furnished to do so,
|
1987 | * subject to the following conditions:
|
1988 | *
|
1989 | * The above copyright notice and this permission notice shall be included in
|
1990 | * all copies or substantial portions of the Software.
|
1991 | *
|
1992 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
1993 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
1994 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
1995 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
1996 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
1997 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1998 | */
|
1999 | /**
|
2000 | * Create a new Thing with existing values replaced by the given URL for the given Predicate.
|
2001 | *
|
2002 | * To preserve existing values, see [[addUrl]].
|
2003 | *
|
2004 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2005 | *
|
2006 | * @param thing Thing to set a URL value on.
|
2007 | * @param predicate Predicate for which to set the given URL value.
|
2008 | * @param url URL to set on `thing` for the given `predicate`.
|
2009 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2010 | */
|
2011 | const setUrl = (thing, predicate, url) => {
|
2012 | const newThing = removeAll(thing, predicate);
|
2013 | const predicateNode = asNamedNode(predicate);
|
2014 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, toNode(url)));
|
2015 | return newThing;
|
2016 | };
|
2017 | /** @hidden Alias of [[setUrl]] for those who prefer IRI terminology. */
|
2018 | const setIri = setUrl;
|
2019 | /**
|
2020 | * Create a new Thing with existing values replaced by the given boolean for the given Predicate.
|
2021 | *
|
2022 | * To preserve existing values, see [[addBoolean]].
|
2023 | *
|
2024 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2025 | *
|
2026 | * @param thing Thing to set a boolean value on.
|
2027 | * @param predicate Predicate for which to set the given boolean value.
|
2028 | * @param value Boolean to set on `thing` for the given `predicate`.
|
2029 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2030 | */
|
2031 | const setBoolean = (thing, predicate, value) => {
|
2032 | return setLiteralOfType(thing, predicate, serializeBoolean(value), xmlSchemaTypes.boolean);
|
2033 | };
|
2034 | /**
|
2035 | * Create a new Thing with existing values replaced by the given datetime for the given Predicate.
|
2036 | *
|
2037 | * To preserve existing values, see [[addDatetime]].
|
2038 | *
|
2039 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2040 | *
|
2041 | * @param thing Thing to set an datetime value on.
|
2042 | * @param predicate Predicate for which to set the given datetime value.
|
2043 | * @param value Datetime to set on `thing` for the given `predicate`.
|
2044 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2045 | */
|
2046 | const setDatetime = (thing, predicate, value) => {
|
2047 | return setLiteralOfType(thing, predicate, serializeDatetime(value), xmlSchemaTypes.dateTime);
|
2048 | };
|
2049 | /**
|
2050 | * Create a new Thing with existing values replaced by the given decimal for the given Predicate.
|
2051 | *
|
2052 | * To preserve existing values, see [[addDecimal]].
|
2053 | *
|
2054 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2055 | *
|
2056 | * @param thing Thing to set a decimal value on.
|
2057 | * @param predicate Predicate for which to set the given decimal value.
|
2058 | * @param value Decimal to set on `thing` for the given `predicate`.
|
2059 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2060 | */
|
2061 | const setDecimal = (thing, predicate, value) => {
|
2062 | return setLiteralOfType(thing, predicate, serializeDecimal(value), xmlSchemaTypes.decimal);
|
2063 | };
|
2064 | /**
|
2065 | * Create a new Thing with existing values replaced by the given integer for the given Predicate.
|
2066 | *
|
2067 | * To preserve existing values, see [[addInteger]].
|
2068 | *
|
2069 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2070 | *
|
2071 | * @param thing Thing to set an integer value on.
|
2072 | * @param predicate Predicate for which to set the given integer value.
|
2073 | * @param value Integer to set on `thing` for the given `predicate`.
|
2074 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2075 | */
|
2076 | const setInteger = (thing, predicate, value) => {
|
2077 | return setLiteralOfType(thing, predicate, serializeInteger(value), xmlSchemaTypes.integer);
|
2078 | };
|
2079 | function setStringInLocale(thing, predicate, value, locale) {
|
2080 | const literal = DataFactory.literal(value, normalizeLocale(locale));
|
2081 | return setLiteral(thing, predicate, literal);
|
2082 | }
|
2083 | /**
|
2084 | * Create a new Thing with existing values replaced by the given unlocalised string for the given Predicate.
|
2085 | *
|
2086 | * To preserve existing values, see [[addStringUnlocalized]].
|
2087 | *
|
2088 | * The original `thing` is not modified; this function returns a cloned Thing with updated values.
|
2089 | *
|
2090 | * @param thing Thing to set an unlocalised string value on.
|
2091 | * @param predicate Predicate for which to set the given unlocalised string value.
|
2092 | * @param value Unlocalised string to set on `thing` for the given `predicate`.
|
2093 | * @returns A new Thing equal to the input Thing with existing values replaced by the given value for the given Predicate.
|
2094 | */
|
2095 | const setStringUnlocalized = (thing, predicate, value) => {
|
2096 | return setLiteralOfType(thing, predicate, value, xmlSchemaTypes.string);
|
2097 | };
|
2098 | function setNamedNode(thing, predicate, value) {
|
2099 | const newThing = removeAll(thing, predicate);
|
2100 | const predicateNode = asNamedNode(predicate);
|
2101 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, value));
|
2102 | return newThing;
|
2103 | }
|
2104 | function setLiteral(thing, predicate, value) {
|
2105 | const newThing = removeAll(thing, predicate);
|
2106 | const predicateNode = asNamedNode(predicate);
|
2107 | newThing.add(DataFactory.quad(toNode(newThing), predicateNode, value));
|
2108 | return newThing;
|
2109 | }
|
2110 | function setLiteralOfType(thing, predicate, value, type) {
|
2111 | const literal = DataFactory.literal(value, type);
|
2112 | return setLiteral(thing, predicate, literal);
|
2113 | }
|
2114 |
|
2115 | /**
|
2116 | * Copyright 2020 Inrupt Inc.
|
2117 | *
|
2118 | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
2119 | * of this software and associated documentation files (the "Software"), to deal in
|
2120 | * the Software without restriction, including without limitation the rights to use,
|
2121 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
2122 | * Software, and to permit persons to whom the Software is furnished to do so,
|
2123 | * subject to the following conditions:
|
2124 | *
|
2125 | * The above copyright notice and this permission notice shall be included in
|
2126 | * all copies or substantial portions of the Software.
|
2127 | *
|
2128 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
2129 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
2130 | * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
2131 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
2132 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
2133 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2134 | */
|
2135 | /**
|
2136 | * Find out what Access Modes have been granted to a given Agent specifically for a given LitDataset.
|
2137 | *
|
2138 | * Keep in mind that this function will not tell you what access the given Agent has through other ACL rules, e.g. public or group-specific permissions.
|
2139 | *
|
2140 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2141 | *
|
2142 | * @param dataset The LitDataset to which the given Agent may have been granted access.
|
2143 | * @param agent WebID of the Agent for which to retrieve what access it has to the Resource.
|
2144 | * @returns Which Access Modes have been granted to the Agent specifically for the given LitDataset, or `null` if it could not be determined (e.g. because the current user does not have Control Access to a given Resource or its Container).
|
2145 | */
|
2146 | function unstable_getAgentAccessModesOne(dataset, agent) {
|
2147 | if (unstable_hasResourceAcl(dataset)) {
|
2148 | const resourceAcl = unstable_getResourceAcl(dataset);
|
2149 | return unstable_getAgentResourceAccessModesOne(resourceAcl, agent);
|
2150 | }
|
2151 | if (unstable_hasFallbackAcl(dataset)) {
|
2152 | const fallbackAcl = unstable_getFallbackAcl(dataset);
|
2153 | return unstable_getAgentDefaultAccessModesOne(fallbackAcl, agent);
|
2154 | }
|
2155 | return null;
|
2156 | }
|
2157 | /**
|
2158 | * Find out what Access Modes have been granted to specific Agents for a given LitDataset.
|
2159 | *
|
2160 | * Keep in mind that this function will not tell you what access arbitrary Agents might have through other ACL rules, e.g. public or group-specific permissions.
|
2161 | *
|
2162 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2163 | *
|
2164 | * @param dataset The LitDataset to which Agents may have been granted access.
|
2165 | * @returns Which Access Modes have been granted to which Agents specifically for the given LitDataset, or `null` if it could not be determined (e.g. because the current user does not have Control Access to a given Resource or its Container).
|
2166 | */
|
2167 | function unstable_getAgentAccessModesAll(dataset) {
|
2168 | if (unstable_hasResourceAcl(dataset)) {
|
2169 | const resourceAcl = unstable_getResourceAcl(dataset);
|
2170 | return unstable_getAgentResourceAccessModesAll(resourceAcl);
|
2171 | }
|
2172 | if (unstable_hasFallbackAcl(dataset)) {
|
2173 | const fallbackAcl = unstable_getFallbackAcl(dataset);
|
2174 | return unstable_getAgentDefaultAccessModesAll(fallbackAcl);
|
2175 | }
|
2176 | return null;
|
2177 | }
|
2178 | /**
|
2179 | * Given an ACL LitDataset, find out which access modes it provides to an Agent for its associated Resource.
|
2180 | *
|
2181 | * Keep in mind that this function will not tell you:
|
2182 | * - what access the given Agent has through other ACL rules, e.g. public or group-specific permissions.
|
2183 | * - what access the given Agent has to child Resources, in case the associated Resource is a Container.
|
2184 | *
|
2185 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2186 | *
|
2187 | * @param aclDataset The LitDataset that contains Access-Control List rules.
|
2188 | * @param agent WebID of the Agent for which to retrieve what access it has to the Resource.
|
2189 | * @returns Which Access Modes have been granted to the Agent specifically for the Resource the given ACL LitDataset is associated with.
|
2190 | */
|
2191 | function unstable_getAgentResourceAccessModesOne(aclDataset, agent) {
|
2192 | const allRules = internal_getAclRules(aclDataset);
|
2193 | const resourceRules = internal_getResourceAclRulesForResource(allRules, aclDataset.accessTo);
|
2194 | const agentResourceRules = getAgentAclRulesForAgent(resourceRules, agent);
|
2195 | const agentAccessModes = agentResourceRules.map(internal_getAccessModes);
|
2196 | return internal_combineAccessModes(agentAccessModes);
|
2197 | }
|
2198 | /**
|
2199 | * Given an ACL LitDataset, find out which access modes it provides to specific Agents for the associated Resource.
|
2200 | *
|
2201 | * Keep in mind that this function will not tell you:
|
2202 | * - what access arbitrary Agents might have been given through other ACL rules, e.g. public or group-specific permissions.
|
2203 | * - what access arbitrary Agents have to child Resources, in case the associated Resource is a Container.
|
2204 | *
|
2205 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2206 | *
|
2207 | * @param aclDataset The LitDataset that contains Access-Control List rules.
|
2208 | * @returns Which Access Modes have been granted to which Agents specifically for the Resource the given ACL LitDataset is associated with.
|
2209 | */
|
2210 | function unstable_getAgentResourceAccessModesAll(aclDataset) {
|
2211 | const allRules = internal_getAclRules(aclDataset);
|
2212 | const resourceRules = internal_getResourceAclRulesForResource(allRules, aclDataset.accessTo);
|
2213 | const agentResourceRules = getAgentAclRules(resourceRules);
|
2214 | return getAccessModesByAgent(agentResourceRules);
|
2215 | }
|
2216 | /**
|
2217 | * Given an ACL LitDataset, find out which access modes it provides to an Agent for the associated Container Resource's child Resources.
|
2218 | *
|
2219 | * Keep in mind that this function will not tell you:
|
2220 | * - what access the given Agent has through other ACL rules, e.g. public or group-specific permissions.
|
2221 | * - what access the given Agent has to Container Resource itself (see [[unstable_getAgentResourceAccessModesOne]] for that).
|
2222 | *
|
2223 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2224 | *
|
2225 | * @param aclDataset The LitDataset that contains Access-Control List rules for a certain Container.
|
2226 | * @param agent WebID of the Agent for which to retrieve what access it has to the Container's children.
|
2227 | * @returns Which Access Modes have been granted to the Agent specifically for the children of the Container associated with the given ACL LitDataset.
|
2228 | */
|
2229 | function unstable_getAgentDefaultAccessModesOne(aclDataset, agent) {
|
2230 | const allRules = internal_getAclRules(aclDataset);
|
2231 | const resourceRules = internal_getDefaultAclRulesForResource(allRules, aclDataset.accessTo);
|
2232 | const agentResourceRules = getAgentAclRulesForAgent(resourceRules, agent);
|
2233 | const agentAccessModes = agentResourceRules.map(internal_getAccessModes);
|
2234 | return internal_combineAccessModes(agentAccessModes);
|
2235 | }
|
2236 | /**
|
2237 | * Given an ACL LitDataset, find out which access modes it provides to specific Agents for the associated Container Resource's child Resources.
|
2238 | *
|
2239 | * Keep in mind that this function will not tell you:
|
2240 | * - what access arbitrary Agents might have been given through other ACL rules, e.g. public or group-specific permissions.
|
2241 | * - what access arbitrary Agents have to the Container Resource itself (see [[unstable_getAgentResourceAccessModesAll]] for that).
|
2242 | *
|
2243 | * Also, please note that this function is still experimental: its API can change in non-major releases.
|
2244 | *
|
2245 | * @param aclDataset The LitDataset that contains Access-Control List rules.
|
2246 | * @returns Which Access Modes have been granted to which Agents specifically for the children of the Container associated with the given ACL LitDataset.
|
2247 | */
|
2248 | function unstable_getAgentDefaultAccessModesAll(aclDataset) {
|
2249 | const allRules = internal_getAclRules(aclDataset);
|
2250 | const resourceRules = internal_getDefaultAclRulesForResource(allRules, aclDataset.accessTo);
|
2251 | const agentResourceRules = getAgentAclRules(resourceRules);
|
2252 | return getAccessModesByAgent(agentResourceRules);
|
2253 | }
|
2254 | function getAgentAclRulesForAgent(aclRules, agent) {
|
2255 | return aclRules.filter((rule) => appliesToAgent(rule, agent));
|
2256 | }
|
2257 | function appliesToAgent(aclRule, agent) {
|
2258 | return getIriAll(aclRule, acl.agent).includes(agent);
|
2259 | }
|
2260 | function getAgentAclRules(aclRules) {
|
2261 | return aclRules.filter(isAgentAclRule);
|
2262 | }
|
2263 | function isAgentAclRule(aclRule) {
|
2264 | return getIriOne(aclRule, acl.agent) !== null;
|
2265 | }
|
2266 | function getAccessModesByAgent(aclRules) {
|
2267 | const agentAccess = {};
|
2268 | aclRules.forEach((rule) => {
|
2269 | const ruleAgents = getIriAll(rule, acl.agent);
|
2270 | const accessModes = internal_getAccessModes(rule);
|
2271 | // A rule might apply to multiple agents. If multiple rules apply to the same agent, the Access
|
2272 | // Modes granted by those rules should be combined:
|
2273 | ruleAgents.forEach((agent) => {
|
2274 | agentAccess[agent] =
|
2275 | typeof agentAccess[agent] === "undefined"
|
2276 | ? accessModes
|
2277 | : internal_combineAccessModes([agentAccess[agent], accessModes]);
|
2278 | });
|
2279 | });
|
2280 | return agentAccess;
|
2281 | }
|
2282 |
|
2283 | export { addBoolean, addDatetime, addDecimal, addInteger, addIri, addLiteral, addNamedNode, addStringInLocale, addStringUnlocalized, addUrl, asIri, asUrl, createLitDataset, createThing, fetchLitDataset, getBooleanAll, getBooleanOne, getDatetimeAll, getDatetimeOne, getDecimalAll, getDecimalOne, getIntegerAll, getIntegerOne, getIriAll, getIriOne, getLiteralAll, getLiteralOne, getNamedNodeAll, getNamedNodeOne, getStringInLocaleAll, getStringInLocaleOne, getStringUnlocalizedAll, getStringUnlocalizedOne, getThingAll, getThingOne, getUrlAll, getUrlOne, removeAll, removeBoolean, removeDatetime, removeDecimal, removeInteger, removeIri, removeLiteral, removeNamedNode, removeStringInLocale, removeStringUnlocalized, removeThing, removeUrl, saveLitDatasetAt, saveLitDatasetInContainer, setBoolean, setDatetime, setDecimal, setInteger, setIri, setLiteral, setNamedNode, setStringInLocale, setStringUnlocalized, setThing, setUrl, unstable_deleteFile, unstable_fetchFile, unstable_fetchLitDatasetWithAcl, unstable_getAgentAccessModesAll, unstable_getAgentAccessModesOne, unstable_getAgentDefaultAccessModesAll, unstable_getAgentDefaultAccessModesOne, unstable_getAgentResourceAccessModesAll, unstable_getAgentResourceAccessModesOne, unstable_getFallbackAcl, unstable_getResourceAcl, unstable_hasFallbackAcl, unstable_hasResourceAcl, unstable_overwriteFile, unstable_saveFileInContainer };
|