Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue#631bis #636

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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%"
Expand Down
17 changes: 7 additions & 10 deletions src/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -1274,13 +1274,7 @@ export default class Fetcher implements CallbackifyInterface {
now.getSeconds() + '.' + now.getMilliseconds() + '] ' + statusMessage
// </Debug>
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)
}

/**
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -2004,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/') ||
Expand Down
33 changes: 23 additions & 10 deletions src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,25 +871,38 @@ 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 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) { // loose equality for null and undefined
const response = this.any(request, this.sym(`${linkNamespaceURI}response`), null, meta) as Quad_Subject
if (response !== undefined) { // ts
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)
}
}
this.removeMatches(this.sym(doc.value), null, null, meta) // content-type
this.removeMatches(doc as Quad_Subject, null, null, meta)
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
Expand Down
119 changes: 97 additions & 22 deletions tests/unit/indexed-formula-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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: <http://www.w3.org/2007/ont/http#>.
@prefix httph: <http://www.w3.org/2007/ont/httph#>.
@prefix tabont: <http://www.w3.org/2007/ont/link#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix pro: <https://bob.localhost:8443/profile/>.
@prefix tur: <http://www.w3.org/ns/iana/media-types/text/turtle#>.

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
'<card.acl>; rel=\"acl\", <card.meta>; rel=\"describedBy\", <http://www.w3.org/ns/ldp#Resource>; 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: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.

<#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)
})
})
})
38 changes: 30 additions & 8 deletions tests/unit/update-manager-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,26 @@ const st3 = $rdf.st(baz, p, 333, doc2)
const httpResultsText = `
@prefix httph: <http://www.w3.org/2007/ont/httph#> .
@prefix link: <http://www.w3.org/2007/ont/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')
}

Expand Down Expand Up @@ -223,6 +238,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)
Expand All @@ -233,13 +259,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)
})

Expand All @@ -248,4 +270,4 @@ describe('UpdateManager', () => {



})
})
Loading