From 3bf1383b2f3597ce24f48f7600e24159e231365e Mon Sep 17 00:00:00 2001 From: jeff-zucker Date: Tue, 17 Nov 2020 15:21:10 -0800 Subject: [PATCH] patch fixes; deprecate global --- package.json | 2 +- src/rest-patch.js | 6 ++-- src/rest.js | 72 +++++++++++++++++++++++------------------------ tests/all.js | 15 ++++++++-- 4 files changed, 51 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 0e60b2a..dfa69b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solid-rest", - "version": "1.2.6", + "version": "1.2.7", "author": "Jeff Zucker", "license": "MIT", "description": "treat any storage as a mini Solid server", diff --git a/src/rest-patch.js b/src/rest-patch.js index ead210e..f6c070f 100644 --- a/src/rest-patch.js +++ b/src/rest-patch.js @@ -24,7 +24,7 @@ class RestPatch { // Obtain details of the patch document const patch = { text: options.body.toString(), - contentType: options.headers['Content-Type'] + contentType: options.headers['content-type'] // normalized to lowercase } const parsePatch = PATCH_PARSERS[patch.contentType] if (!parsePatch) { @@ -58,7 +58,7 @@ class RestPatch { graph.applyPatch(patchObject, graph.sym(url), (err) => { if (err) { const message = err.message || err // returns string at the moment - return reject(`409 : The patch could not be applied. ${message}`) // is this correct : not tested + return reject(new Error(`409 : The patch could not be applied. ${message}`)) // is this correct : not tested } resolve(graph) }) @@ -122,7 +122,7 @@ async function parsePatchN3 (targetURI, patchURI, patchText) { } // Queries the store with the given SPARQL query and returns the first result -queryForFirstResult = (store, sparql) => { +function queryForFirstResult(store, sparql) { return new Promise((resolve, reject) => { const query = $rdf.SPARQLToQuery(sparql, false, store) store.query(query, resolve, null, () => reject(new Error('409 : No results.'))) // TODO check status diff --git a/src/rest.js b/src/rest.js index 7dbba8a..40ad69d 100644 --- a/src/rest.js +++ b/src/rest.js @@ -13,13 +13,28 @@ let patch; class SolidRest { -constructor( handlers,auth,sessionId ) { - const Global = (typeof window !="undefined") ? window - : (typeof global !="undefined") ? global - : {}; - patch = Global.$rdf ? new RestPatch(Global.$rdf) : null; +//constructor( handlers,auth,sessionId ) { +constructor( options ) { + let handlers; + if(typeof options === "object"){ + if( Object.keys(options)[0] === "0" ) { + handlers = options // ARRAY + options = {} + } + else { + handlers = options.handlers || null + } + } + else { + options = {} + } + let $rdf = (options.parser) ? options.parser + : (typeof window !="undefined" && window.$rdf) ? window.$rdf + : (typeof global !="undefined" && global.$rdf) ? global.$rdf + : null; + patch = ($rdf) ? new RestPatch($rdf) : null; this.storageHandlers = {} - if( typeof handlers ==="undefined" || handlers.length===0) { + if( !handlers ) { if( typeof window ==="undefined") { let File = require('./file.js'); let Mem = require('./localStorage.js'); @@ -39,7 +54,7 @@ constructor( handlers,auth,sessionId ) { // `) this.storageHandlers[handler.prefix] = handler }) - return this.addFetch(auth,sessionId) + // return this.addFetch(auth,sessionId) } /* auth can be solid-auth-cli or solid-client-authn, or (default) cross-fetch @@ -83,21 +98,8 @@ async itemExists(pathname,options){ async fetch(uri, options = {}) { let self = this - options = options || {} - - // cxRes -/* - options.url = decodeURIComponent(uri) - - let pathname = decodeURIComponent(Url.parse(uri).pathname) - let scheme = Url.parse(uri).protocol - let prefix = scheme.match("file") - ? 'file' - : uri.replace(scheme+'//','').replace(/\/.*$/,'') - options.scheme = scheme - options.rest_prefix = prefix -*/ -/**/ + options = _normalizeOptions(options) + options.headers = _normalizeOptions(options.headers) const url = new URL(uri) options.scheme = url.protocol let pathname, path @@ -116,7 +118,6 @@ async fetch(uri, options = {}) { path = libPath.posix } options.mungedPath = path || libPath - /**/ if(!self.storage){ @@ -127,9 +128,6 @@ async fetch(uri, options = {}) { self.storage=()=>{return self.storageHandlers[options.rest_prefix]} } } - - options.method = (options.method || options.Method || 'GET').toUpperCase() - options.headers = options.headers || {} const [objectType,objectExists] = await self.storage(options).getObjectType(pathname,options) @@ -251,7 +249,7 @@ async fetch(uri, options = {}) { const [patchStatus, resContent] = await patch.patchContent(content, contentType, options) if ( patchStatus !== 200) return _response(resContent, resOptions, patchStatus) options.body = resContent - options.headers['Content-Type'] = contentType + options.headers['content-type'] = contentType } catch (e) { throw _response(e, resOptions, parseInt(e)) } // PUT content to file @@ -473,19 +471,19 @@ function _mungePath(pathname, slug, options) { return pathname; } -/* not needed? location returns pathname, not URL - -function mapPathToUrl (pathname, options) { - let prefix = options.rest_prefix; - if (prefix === 'file') { - // windows file starts with a letter, linux file starts with a '/' - prefix = pathname.includes(':/') ? '/' : '' // windows or linux +/** Normalize content-type/Content-type and method/Method + */ +function _normalizeOptions(opts){ + let newOpts = {}; + for(var o in opts){ + newOpts[o.toLowerCase()] = opts[o]; } - return options.scheme + '//' + prefix + pathname -} -*/ + newOpts.method = newOpts.method ? newOpts.method.toUpperCase() : 'GET'; + return newOpts; +} } // end of fetch() + } // end of SolidRest() module.exports = exports = SolidRest diff --git a/tests/all.js b/tests/all.js index a087380..e2bfb81 100644 --- a/tests/all.js +++ b/tests/all.js @@ -1,13 +1,17 @@ "use strict"; -global.$rdf = require('rdflib') // SAME TEST SHOULD WORK FOR solid-rest AND solid-node-client // //const SolidNodeClient = require('../').SolidNodeClient //const client = new SolidNodeClient() const SolidRest = require('../') -const client = new SolidRest() + + +// global.$rdf = require('rdflib') +// const client = new SolidRest() +const $rdf = require('rdflib'); +const client = new SolidRest({ parser:$rdf }) /** Silence rdflib chatty information about patch * Send console.log() to a logfile @@ -82,6 +86,8 @@ async function getConfig(scheme){ const patchSparql = `INSERT { :new <#temp> <#245>; "n0:240" .} DELETE { <> a :test.}` + const patchSparql1 = `INSERT { :new <#temp> <#245>; "n0:240" .} + DELETE { <> a :NONEXISTANT.}` const patchN3_1 = (url) => `@prefix solid: . @prefix schem: . @prefix : <#>. @@ -181,6 +187,7 @@ const resPatchN3_2 = [`@prefix : <#>. patchN3_2 : patchN3_2(file1), patchN3_3 : patchN3_3(file1), patchSparql: patchSparql, + patchSparql1: patchSparql1, resPatchSparql: resPatchSparql, resPatchN3_1 : resPatchN3_1, resPatchN3_2 : resPatchN3_2 @@ -282,9 +289,11 @@ async function run(scheme){ res = await PATCH( cfg.file1,cfg.text, 'application/sparql-update' ) ok("400 patch erroneous patchContent",res.status==400, res) + res = await PATCH( cfg.file1,cfg.patchSparql1, 'application/sparql-update' ) + ok("409 patch failed, cannot delete not existant triple",res.status==409, res) + res = await PATCH( cfg.file1,cfg.patchSparql, 'application/sparql-update' ) res1 = await GET( cfg.file1 ) - //console.warn(res1.statusText.toString()) ok("200 patch sparql insert, delete to existing resource",res.status==200 && testPatch(res1, cfg.resPatchSparql), res1) res = await PATCH( cfg.file1,cfg.patchN3_1, 'text/n3' )