From 1beb2c7548d0c34c540fc78709b20772c9a4c0b2 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Sat, 3 Feb 2024 22:52:06 +0100 Subject: [PATCH 1/5] removeMetadata --- src/store.ts | 43 +++++++++++++++++++++++-------- tests/unit/update-manager-test.js | 15 ++++++++--- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/store.ts b/src/store.ts index 1b4714958..0ba524261 100644 --- a/src/store.ts +++ b/src/store.ts @@ -871,25 +871,46 @@ export default class IndexedFormula extends Formula { // IN future - allow pass } /** - * Removes all statements in a doc, along with the related metadata including request/response + * Removes all metadata * @param doc - The document / graph */ - removeDocument(doc: Quad_Graph): IndexedFormula { - const meta = this.sym('chrome://TheCurrentSession') // or this.rdfFactory.namedNode('chrome://TheCurrentSession') - const linkNamespaceURI = 'http://www.w3.org/2007/ont/link#' // alain - // remove request/response and metadata - const requests = this.statementsMatching(undefined, this.sym(`${linkNamespaceURI}requestedURI`), this.rdfFactory.literal(doc.value), meta).map(st => st.subject) + removeMetadata(doc: Quad_Graph): IndexedFormula { + const meta = this.fetcher?.appNode // this.sym('chrome://TheCurrentSession') + const linkNamespaceURI = 'http://www.w3.org/2007/ont/link#' + const kb = this + // removeMatches() --> removeMany() --> remove() fails on Collection + function removeBySubject (subject) { + const sts = kb.statementsMatching(subject, null, null, meta) + // console.log(sts) + for (var i = 0; i < sts.length; i++) { + kb.removeStatement(sts[i]) + } + } + const requests = this.statementsMatching(null, this.sym(`${linkNamespaceURI}requestedURI`), this.rdfFactory.literal(doc.value), meta).map(st => st.subject) for (var r = 0; r < requests.length; r++) { const request = requests[r] - if (request !== undefined) { - this.removeMatches(request, null, null, meta) + if (request != null) { // null or undefined const response = this.any(request, this.sym(`${linkNamespaceURI}response`), null, meta) as Quad_Subject - if (response !== undefined) { // ts - this.removeMatches(response, null, null, meta) + // console.log('REQUEST ' + request.value) + removeBySubject(request) + if (response != null) { // null or undefined + // console.log('RESPONSE ' + response.value) + removeBySubject(response) } } } - this.removeMatches(this.sym(doc.value), null, null, meta) // content-type + // console.log('DOCTYPE ' + doc.value) + removeBySubject(doc) + return this + } + + /** + * Removes all statements in a doc, along with the related metadata including request/response + * @param doc - The document / graph + */ + removeDocument(doc: Quad_Graph): IndexedFormula { + // remove request/response and metadata + this.removeMetadata(doc) // remove document var sts: Quad[] = this.statementsMatching(undefined, undefined, undefined, doc).slice() // Take a copy as this is the actual index diff --git a/tests/unit/update-manager-test.js b/tests/unit/update-manager-test.js index 9320e6519..d0dff1342 100644 --- a/tests/unit/update-manager-test.js +++ b/tests/unit/update-manager-test.js @@ -223,6 +223,17 @@ describe('UpdateManager', () => { expect(updater.editable(doc1)).to.equal(undefined) }) + it('Should not detect a document is editable from metadata after removeMetadata', () => { + loadMeta(updater.store) + updater.store.removeMetadata(doc1) + expect(updater.editable(doc1)).to.equal(undefined) + }) + + it('Should not detect a document is editable from metadata after removeDocument', () => { + loadMeta(updater.store) + updater.store.removeDocument(doc1) + expect(updater.editable(doc1)).to.equal(undefined) + }) it('Async version should detect a document is editable from metadata', async () => { loadMeta(updater.store) @@ -233,13 +244,9 @@ describe('UpdateManager', () => { it('Async version should not detect a document is editable from metadata after flush', async () => { loadMeta(updater.store) - expect(updater.editable(doc1)).to.equal('SPARQL') - updater.flagAuthorizationMetadata() - const result = await updater.checkEditable(doc1) - expect(result).to.equal(undefined) }) From 3c883a8aa36c81dceb66c6e9d785c1229c08e6d0 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Sat, 10 Feb 2024 19:50:24 +0100 Subject: [PATCH 2/5] replace object collection --- src/fetcher.ts | 11 +-- src/store.ts | 26 +++---- tests/unit/indexed-formula-test.js | 117 +++++++++++++++++++++++------ tests/unit/update-manager-test.js | 21 +++++- 4 files changed, 125 insertions(+), 50 deletions(-) diff --git a/src/fetcher.ts b/src/fetcher.ts index cb449c11c..8af85e345 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -34,7 +34,7 @@ import rdfParse from './parse' import { parseRDFaDOM } from './rdfaparser' import RDFParser from './rdfxmlparser' import * as Uri from './uri' -import { isCollection, isNamedNode} from './utils/terms' +import { isNamedNode } from './utils/terms' import * as Util from './utils-js' import serialize from './serialize' import crossFetch, { Headers } from 'cross-fetch' @@ -1274,13 +1274,7 @@ export default class Fetcher implements CallbackifyInterface { now.getSeconds() + '.' + now.getMilliseconds() + '] ' + statusMessage // let kb = this.store - - const statusNode = kb.the(req, this.ns.link('status')) - if (isCollection(statusNode)) { - statusNode.append(kb.rdfFactory.literal(statusMessage)) - } else { - log.warn('web.js: No list to add to: ' + statusNode + ',' + statusMessage) - } + kb.add(req, this.ns.link('status'), kb.rdfFactory.literal(statusMessage), this.appNode) } /** @@ -1725,7 +1719,6 @@ export default class Fetcher implements CallbackifyInterface { // We store the docuri as a string, not as a node, // see https://github.com/linkeddata/rdflib.js/pull/427#pullrequestreview-447910061 kb.add(req, this.ns.link('requestedURI'), kb.rdfFactory.literal(docuri), this.appNode) - kb.add(req, this.ns.link('status'), kb.collection(), this.appNode) } saveResponseMetadata ( diff --git a/src/store.ts b/src/store.ts index 0ba524261..56ecebe58 100644 --- a/src/store.ts +++ b/src/store.ts @@ -877,30 +877,22 @@ export default class IndexedFormula extends Formula { // IN future - allow pass removeMetadata(doc: Quad_Graph): IndexedFormula { const meta = this.fetcher?.appNode // this.sym('chrome://TheCurrentSession') const linkNamespaceURI = 'http://www.w3.org/2007/ont/link#' - const kb = this - // removeMatches() --> removeMany() --> remove() fails on Collection - function removeBySubject (subject) { - const sts = kb.statementsMatching(subject, null, null, meta) - // console.log(sts) - for (var i = 0; i < sts.length; i++) { - kb.removeStatement(sts[i]) - } - } const requests = this.statementsMatching(null, this.sym(`${linkNamespaceURI}requestedURI`), this.rdfFactory.literal(doc.value), meta).map(st => st.subject) for (var r = 0; r < requests.length; r++) { const request = requests[r] - if (request != null) { // null or undefined + if (request != null) { // loose equality for null and undefined const response = this.any(request, this.sym(`${linkNamespaceURI}response`), null, meta) as Quad_Subject - // console.log('REQUEST ' + request.value) - removeBySubject(request) - if (response != null) { // null or undefined - // console.log('RESPONSE ' + response.value) - removeBySubject(response) + if (response != null) { + this.removeMatches(response, null, null, meta) + } + const status = this.any(request, this.sym(`${linkNamespaceURI}status`), null, meta) as Quad_Subject + if (status != null) { + this.removeMatches(status, null, null, meta) } + this.removeMatches(request, null, null, meta) } } - // console.log('DOCTYPE ' + doc.value) - removeBySubject(doc) + this.removeMatches(doc as Quad_Subject, null, null, meta) return this } diff --git a/tests/unit/indexed-formula-test.js b/tests/unit/indexed-formula-test.js index 4501d55f2..6d56d22a9 100644 --- a/tests/unit/indexed-formula-test.js +++ b/tests/unit/indexed-formula-test.js @@ -7,6 +7,8 @@ import IndexedFormula from '../../src/store' import NamedNode from '../../src/named-node' import { RDFArrayRemove } from '../../src/utils-js' import DataFactory from '../../src/factories/rdflib-data-factory' +import parse from '../../src/parse' +import serialize from '../../src/serialize' describe('IndexedFormula', () => { const g0 = NamedNode.fromValue('https://example.com/graph0') @@ -319,25 +321,98 @@ describe('IndexedFormula', () => { }); describe('removeMatches', () => { - it ('removes matching statements', () => { - const store = new IndexedFormula() - store.add([triple2, triple3, triple4]) - expect(store.statements.length).to.eq(3) - store.removeMatches(null, null, triple3.object, null) - - expect(store.statements.length).to.eq(1) - expect(store.holds(s2, p2, o2)).to.be.true() - }) - it ('does the same as remove of matches', () => { - const store0 = new IndexedFormula() - store0.add([triple2, triple3, triple4]) - const store1 = new IndexedFormula() - store1.add([triple2, triple3, triple4]) - store0.remove(store0.match(null, null, triple3.object, null)) - store1.removeMatches(null, null, triple3.object, null) - - expect(store0.holdsStatement(store1)).to.be.true() - expect(store1.holdsStatement(store0)).to.be.true() - }) - }); + it ('removes matching statements', () => { + const store = new IndexedFormula() + store.add([triple2, triple3, triple4]) + expect(store.statements.length).to.eq(3) + store.removeMatches(null, null, triple3.object, null) + + expect(store.statements.length).to.eq(1) + expect(store.holds(s2, p2, o2)).to.be.true() + }) + it ('does the same as remove of matches', () => { + const store0 = new IndexedFormula() + store0.add([triple2, triple3, triple4]) + const store1 = new IndexedFormula() + store1.add([triple2, triple3, triple4]) + store0.remove(store0.match(null, null, triple3.object, null)) + store1.removeMatches(null, null, triple3.object, null) + + expect(store0.holdsStatement(store1)).to.be.true() + expect(store1.holdsStatement(store0)).to.be.true() + }) + }) + describe('removeMetadata', () => { + + }) + describe('removeDocument', () => { + const store = new IndexedFormula() + const meta = store.sym('chrome://TheCurrentSession') + const prefixes = `@prefix : <#>. + @prefix http: . + @prefix httph: . + @prefix tabont: . + @prefix rdfs: . + @prefix pro: . + @prefix tur: . + + pro:card a tabont:Document, tabont:RDFDocument, tur:Resource. + +` + const metaContent = prefixes + ` + [ + rdfs:label "[0:16:34] Request for https://bob.localhost:8443/profile/card"; + tabont:requestedURI "https://bob.localhost:8443/profile/card"; + tabont:response + [ + http:status 200; + http:statusText "OK"; + httph:accept-patch + "text/n3, application/sparql-update, application/sparql-update-single-match"; + httph:accept-post "*/*"; + httph:accept-put "*/*"; + httph:access-control-allow-credentials "true"; + httph:access-control-expose-headers + "Authorization, User, Location, Link, Vary, Last-Modified, ETag, Accept-Patch, Accept-Post, Accept-Put, Updates-Via, Allow, WAC-Allow, Content-Length, WWW-Authenticate, MS-Author-Via, X-Powered-By"; + httph:allow "OPTIONS, HEAD, GET, PATCH, POST, PUT, DELETE"; + httph:connection "keep-alive"; + httph:content-type "text/turtle"; + httph:date "Thu, 08 Feb 2024 23:16:35 GMT"; + httph:keep-alive "timeout=5"; + httph:link + '; rel=\"acl\", ; rel=\"describedBy\", ; rel=\"type\"'; + httph:ms-author-via "SPARQL"; + httph:transfer-encoding "chunked"; + httph:updates-via "wss://bob.localhost:8443"; + httph:vary "Accept, Authorization, Origin"; + httph:wac-allow 'user=\"read write append control\",public=\"read\"'; + httph:x-powered-by "solid-server/5.7.9-beta" + ]; + tabont:status + "[0:16:35.259] N3 parsed: 13 triples in 26 lines.", + "[0:16:35.259] Done." + ]. + ` + const voidDoc = `@prefix : <#>. + +` + it ('removeMetada', () => { + parse(metaContent, store, meta.value, 'text/turtle') + store.removeMetadata(store.sym('https://bob.localhost:8443/profile/card')) + expect(serialize(meta, store, meta.uri)).to.eql(voidDoc) + }) + it ('removeDocument', () => { + parse(metaContent, store, meta.value, 'text/turtle') + const doc = store.sym('https://bob.localhost:8443/profile/card') + const docContent = ` + @prefix rdf: . + + <#test> <#value> [ rdf:first 1; rdf:rest [ rdf:first 2; rdf:rest [ rdf:first 3; rdf:rest rdf:nil ]]] . +` + parse(docContent, store, doc.uri, 'text/turtle') + store.removeDocument(store.sym('https://bob.localhost:8443/profile/card')) + expect(serialize(meta, store, meta.uri)).to.eql(voidDoc) + expect(serialize(doc, store, doc.uri)).to.eql(voidDoc) + }) + }) }) diff --git a/tests/unit/update-manager-test.js b/tests/unit/update-manager-test.js index d0dff1342..4f9a574cb 100644 --- a/tests/unit/update-manager-test.js +++ b/tests/unit/update-manager-test.js @@ -36,11 +36,26 @@ const st3 = $rdf.st(baz, p, 333, doc2) const httpResultsText = ` @prefix httph: . @prefix link: . - [] link:requestedURI "${doc.uri}", "${doc2.uri}"; link:response [ httph:accept-patch "application/sparql-update" ]. - ` +[ link:requestedURI "${doc.uri}"; + link:response + [ httph:accept-patch "application/sparql-update"; + httph:accept-post "*/*"; + httph:accept-put "*/*" + ]; + link:status + "[0:16:35.259] N3 parsed: 13 triples in 26 lines.", + "[0:16:35.259] Done." +]. +[ link:requestedURI "${doc2.uri}"; + link:response [ httph:accept-patch "application/sparql-update" ]; + link:status + "[0:16:35.259] N3 parsed: 13 triples in 26 lines.", + "[0:16:35.259] Done." +]. +` function loadMeta (store) { - $rdf.parse(httpResultsText, store, meta.uri) + $rdf.parse(httpResultsText, store, meta.uri) // alain , 'text/turtle') console.log('Loaded metadata') } From 85ca120ed0ad35550080cbf230be31c24231bc11 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Sat, 10 Feb 2024 20:08:55 +0100 Subject: [PATCH 3/5] add collection in metadata content for tests --- tests/unit/indexed-formula-test.js | 6 +++--- tests/unit/update-manager-test.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/unit/indexed-formula-test.js b/tests/unit/indexed-formula-test.js index 6d56d22a9..0c4f3388c 100644 --- a/tests/unit/indexed-formula-test.js +++ b/tests/unit/indexed-formula-test.js @@ -389,8 +389,8 @@ describe('IndexedFormula', () => { httph:x-powered-by "solid-server/5.7.9-beta" ]; tabont:status - "[0:16:35.259] N3 parsed: 13 triples in 26 lines.", - "[0:16:35.259] Done." + ( "[0:16:35.259] N3 parsed: 13 triples in 26 lines." + "[0:16:35.259] Done." ) ]. ` const voidDoc = `@prefix : <#>. @@ -415,4 +415,4 @@ describe('IndexedFormula', () => { expect(serialize(doc, store, doc.uri)).to.eql(voidDoc) }) }) -}) +}) \ No newline at end of file diff --git a/tests/unit/update-manager-test.js b/tests/unit/update-manager-test.js index 4f9a574cb..ffd1bde67 100644 --- a/tests/unit/update-manager-test.js +++ b/tests/unit/update-manager-test.js @@ -49,8 +49,8 @@ const httpResultsText = ` [ link:requestedURI "${doc2.uri}"; link:response [ httph:accept-patch "application/sparql-update" ]; link:status - "[0:16:35.259] N3 parsed: 13 triples in 26 lines.", - "[0:16:35.259] Done." + ( "[0:16:35.259] N3 parsed: 13 triples in 26 lines." + "[0:16:35.259] Done." ) ]. ` @@ -270,4 +270,4 @@ describe('UpdateManager', () => { -}) +}) \ No newline at end of file From 571d058b13547ed421e4fb01c798949627623a1a Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Mon, 19 Feb 2024 18:06:55 +0100 Subject: [PATCH 4/5] fetcher load issue --- src/fetcher.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/fetcher.ts b/src/fetcher.ts index 8af85e345..712ff2aba 100644 --- a/src/fetcher.ts +++ b/src/fetcher.ts @@ -1997,7 +1997,11 @@ export default class Fetcher implements CallbackifyInterface { // Before we parse new data clear old but only on 200 if (options.clearPreviousData) { - kb.removeDocument(options.resource) + // kb.removeDocument(options.resource) + const sts = kb.statementsMatching(undefined, undefined, undefined, options.resource).slice() // Take a copy as this is the actual index + for (let i = 0; i < sts.length; i++) { + kb.removeStatement(sts[i]) + } } let isImage = contentType.includes('image/') || From f2b368042bd9299387590757b68b400072984a24 Mon Sep 17 00:00:00 2001 From: bourgeoa Date: Mon, 19 Feb 2024 18:07:01 +0100 Subject: [PATCH 5/5] 2.2.34-alpha --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7c8ad6c8f..36b04f200 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "rdflib", - "version": "2.2.33", + "version": "2.2.34-alpha", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "rdflib", - "version": "2.2.33", + "version": "2.2.34-alpha", "license": "MIT", "dependencies": { "@babel/runtime": "^7.21.0", diff --git a/package.json b/package.json index 316cfb91a..2c61bc0a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "rdflib", "description": "an RDF library for node.js. Suitable for client and server side.", - "version": "2.2.33", + "version": "2.2.34-alpha", "private": false, "browserslist": [ "> 0.5%"