@solid-rest/core
Advanced tools
Comparing version 2.1.18 to 2.1.19
@@ -7,5 +7,3 @@ "use strict"; | ||
exports.getRequest = getRequest; | ||
var _url = require("url"); | ||
function getRequest(uri, options) { | ||
@@ -17,3 +15,2 @@ const request = normalizeRequestKeys(options); | ||
request.body = request.body || ""; | ||
if (!validUrl(uri)) { | ||
@@ -27,3 +24,2 @@ request.url = null; | ||
} | ||
if (request.url && request.url.endsWith('.dummy')) { | ||
@@ -34,3 +30,2 @@ // rdflib does this !!! | ||
} | ||
return request; | ||
@@ -42,6 +37,4 @@ } | ||
function normalizeRequestKeys(opts) { | ||
let newOpts = {}; | ||
for (var o in opts) { | ||
@@ -52,6 +45,4 @@ if (o === 'host') { | ||
} | ||
return newOpts; | ||
} | ||
const validUrl = s => { | ||
@@ -69,5 +60,4 @@ try { | ||
function normalizeRequestMethod(method) { | ||
return method ? method.toUpperCase() : 'GET'; | ||
} |
@@ -7,14 +7,10 @@ "use strict"; | ||
exports.getItem = getItem; | ||
var _url = _interopRequireDefault(require("url")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
//import libPath from "path"; | ||
//import libPath from "path"; | ||
var pathHandler; | ||
async function getItem(uri, request) { | ||
let url, pname; | ||
pathHandler = await this.perform('GET_PATH_HANDLER', uri); | ||
if (uri.startsWith('file')) { | ||
@@ -27,3 +23,2 @@ url = _url.default.format(request.url); | ||
} | ||
const item = await this.perform('GET_ITEM_INFO', pname, request); | ||
@@ -36,3 +31,2 @@ item.mode = item.mode ? item.mode : { | ||
item.pathname = pname; | ||
if (request.method === 'DELETE' && item.isContainer) { | ||
@@ -46,3 +40,2 @@ let files = await this.perform('GET_FILES', item.pathname); | ||
} | ||
this.getExtension = path => { | ||
@@ -53,6 +46,4 @@ path = path || this.item.pathname || ""; | ||
}; | ||
this.pathSep = pathHandler.sep; | ||
this.basename = pathHandler.extname; | ||
this.mungePath = (pathname, slug, options) => { | ||
@@ -63,3 +54,2 @@ pathname = pathHandler.join(pathname, slug); | ||
}; | ||
pname = request.method === "POST" ? this.mungePath(item.pathname, request.slug) : item.pathname; | ||
@@ -70,5 +60,6 @@ item.extension = this.getExtension(pname); | ||
item.isAcl = pname.match(/\.acl/); // TBD use LinkExt | ||
//item.isAuxResource = item.isAcl || this.extension === '.meta'; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
/* | ||
@@ -75,0 +66,0 @@ let conflict |
@@ -38,9 +38,6 @@ "use strict"; | ||
}; | ||
async function handleRequest(uri, originalRequest) { | ||
const request = this.requestObj = await this.getRequest(uri, originalRequest); // | ||
const item = this.item = await this.getItem(uri, request); // | ||
// Errors we find in the request | ||
if (!request.url || !request.method) return 400; | ||
@@ -51,11 +48,9 @@ if (request.slug.endsWith('/')) return 400; | ||
if (request.method === 'PATCH' && !this.patch) return 405; | ||
if (request.method === 'POST' && !request.headers.link) return 400; // Errors we find by comparing the request & the itemRequested | ||
if (request.method === 'POST' && !request.headers.link) return 400; | ||
// Errors we find by comparing the request & the itemRequested | ||
if (item.isContainer && !item.contentType) item.contentType = "text/turtle"; | ||
if (item.folderFileConfusion) return 400; // can't have both /foo and /foo/ | ||
if (item.patchOnNonRdf) return 400; | ||
if (item.mode.write) item.mode.append = true; | ||
const method = methods[request.method]; | ||
if (item.isAuxResource) { | ||
@@ -65,3 +60,2 @@ if (item.isAcl) method.requiresControl = true; | ||
} | ||
if (!method) console.log(55, request.method); | ||
@@ -71,3 +65,2 @@ if (!method) return 409; | ||
if (method.requiresRead && !item.mode.read || method.requiresAppend && !item.mode.append || method.requiresWrite && !item.mode.write || method.requiresControl && !item.mode.control) return 401; | ||
if (method.requiresContentType && !request.headers['content-type']) { | ||
@@ -77,3 +70,2 @@ // console.log(request.method, "No Content Type"); | ||
} | ||
if (request.method === 'POST') { | ||
@@ -84,3 +76,2 @@ this.item.pathname = await this.generateRandomSlug(this.item.pathname, request.slug); | ||
if (request.method === 'PUT' || request.method === 'POST' || request.method === 'PATCH') { | ||
@@ -91,8 +82,5 @@ // if (item.isContainer) return 405; | ||
} | ||
let response = await this.perform(request.method); | ||
if (!response && request.method === 'DELETE' && item.isContainer) { | ||
let stillExists = await this.perform('ITEM_EXISTS', this.item.pathname); | ||
if (stillExists) { | ||
@@ -102,4 +90,3 @@ return 409; | ||
} | ||
return response; | ||
} // ENDS |
@@ -7,7 +7,4 @@ "use strict"; | ||
exports.handleResponse = handleResponse; | ||
var _crossFetch = require("cross-fetch"); | ||
var _uuid = require("uuid"); | ||
/* | ||
@@ -19,2 +16,3 @@ url : file:///foo/bar.txt | ||
//import libPath from 'path'; | ||
const statusText = { | ||
@@ -34,6 +32,4 @@ 200: "OK", | ||
}; | ||
async function handleResponse(response, originalRequest) { | ||
let wrapHeaders = true; // {headers} instead of headers for Response | ||
let method = originalRequest.method || this.request.method || "GET"; | ||
@@ -51,3 +47,2 @@ let finalResponse = { | ||
*/ | ||
if (typeof response === 'number') { | ||
@@ -74,22 +69,23 @@ wrapHeaders = false; | ||
if (method.match(/(PUT)/) && finalResponse.headers.status == 200) { | ||
finalResponse.headers.status = 201; | ||
} | ||
if (method.match(/(DELETE|GET|HEAD)/) && finalResponse.headers.status == 201) { | ||
finalResponse.headers.status = 200; | ||
} | ||
let headers = {}; | ||
const request = this.requestObj; | ||
const item = this.item; | ||
const pathname = item.pathname; // const fn = libPath.basename(pathname); | ||
const pathname = item.pathname; | ||
// const fn = libPath.basename(pathname); | ||
const fn = pathname.replace(/.*\//, ''); | ||
headers['vary'] = 'accept,authorization,origin'; | ||
headers['access-control-expose-headers'] = 'accept-patch,accept-post,accept-put,allow,content-range,etag,last-modified,link,location,updates-via,wac-allow,www-authenticate'; | ||
headers['content-type'] = this.item.contentType; // CONTENT-TYPE | ||
headers.link = headers.link || createLinkHeader(item); // LINK | ||
const storageHeader = item.pathname === '/' ? ', <http://www.w3.org/ns/pim/space#Storage>; rel="type"' : ''; | ||
headers.link = headers.link || createLinkHeader(item) + storageHeader; // LINK | ||
headers.allow = createAllowHeader(this.patch, this.item.mode); // ALLOW | ||
headers.allow = createAllowHeader(item.pathname); // ALLOW | ||
@@ -102,6 +98,6 @@ headers['wac-allow'] = createWacHeader(this.item.mode); // WAC-ALLOW | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; // NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; | ||
// NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
headers.url = pathname; | ||
if (method === "POST") { | ||
@@ -119,15 +115,14 @@ headers.url = this.request.url; | ||
} | ||
/* if (this.patch) { // ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} */ | ||
if (this.patch) { | ||
// ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
let body = finalResponse.body || this.response.body || ""; // Now we merge headers we created with response headers, prefering response | ||
Object.assign(headers, finalResponse.headers); //alert(finalResponse.headers.status) | ||
Object.assign(headers, finalResponse.headers); | ||
//alert(finalResponse.headers.status) | ||
headers.status = finalResponse.headers.status || this.response.headers.status || 500; | ||
let $rdf = typeof window != "undefined" && window.$rdf ? window.$rdf : typeof global != "undefined" && global.$rdf ? global.$rdf : null; | ||
/* | ||
@@ -158,12 +153,18 @@ async function serialize(uri,body,informat,outformat){ | ||
*/ | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers = createAcceptHeader(request, headers); // ACCEPT | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers.etag = `W/"${(0, _uuid.v4)()}"`; | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; // Now we create & return the Response object | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; | ||
// TODO (?) last-modified | ||
// Now we create & return the Response object | ||
for (var h of Object.keys(headers)) { | ||
if (!headers[h]) delete headers[h]; | ||
} | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; // headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// if(!headers.location.match(/^file:/)) headers.location = "file://"+headers.location; | ||
@@ -173,3 +174,2 @@ | ||
body = ""; | ||
for (let k of Object.keys(headers)) { | ||
@@ -179,3 +179,2 @@ body = body + `${k}:${headers[k]}\n`; | ||
} | ||
if (originalRequest.plainResponse) { | ||
@@ -192,3 +191,2 @@ // from a server that wants to munge | ||
} | ||
wrapHeaders = true; | ||
@@ -203,3 +201,2 @@ headers = wrapHeaders ? { | ||
let responseObject; | ||
try { | ||
@@ -212,3 +209,2 @@ responseObject = new _crossFetch.Response(body, headers, { | ||
} | ||
return responseObject; | ||
@@ -218,3 +214,2 @@ } // end of handleResponse method | ||
function createWacHeader(mode) { | ||
@@ -226,7 +221,26 @@ if (!mode.read && !mode.write) return null; | ||
} | ||
function createAllowHeader(patch, mode) { | ||
return 'OPTIONS,HEAD' + (mode.read ? ',GET' : '') + (mode.write ? ',POST,PUT,DELETE' : '') + (mode.write && patch ? ',PATCH' : ''); | ||
function createAllowHeader(requestPath) { | ||
// root/ root/.acl can't be deleted | ||
let del = requestPath === '/' || requestPath === '/.acl' ? '' : ',DELETE'; | ||
// no PATCH on Container | ||
if (requestPath.endsWith('/')) return 'OPTIONS,HEAD,GET,POST,PUT' + del; | ||
// no POST on Document | ||
else return 'OPTIONS,HEAD,GET,PATCH,PUT' + del; | ||
} | ||
function createAcceptHeader(request, headers) { | ||
const status = headers.status; | ||
// no Accept header | ||
if (request.method.match(/DELETE/) || status >= 500 || status.toString().match(/401|403/)) return headers; | ||
// Accept headers on container | ||
if (request.url.endsWith('/')) { | ||
if (status === 404) headers['accept-put'] = ['*/*']; | ||
headers['accept-post'] = ['*/*']; | ||
} else { | ||
// Accept headers on document | ||
headers['accept-put'] = ['*/*']; | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
return headers; | ||
} | ||
function createLinkHeader(item) { | ||
@@ -237,12 +251,13 @@ let isContainer = item.isContainer; | ||
let ext = item.extension; | ||
if (ext === '.acl') // .acl not controlledBy or describedBy anything | ||
if (ext === '.acl') | ||
// .acl not controlledBy or describedBy anything | ||
return `<http://www.w3.org/ns/ldp#Resource>; rel="type"`;else if (ext === '.meta') { | ||
return `<${fn}.acl>; rel="acl",` // .meta controlledBy .meta.acl | ||
+ `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<${fn}.acl>; rel="acl"` // .meta controlledBy .meta.acl | ||
+ `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else if (isContainer) { | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Container>; rel="type",` + `<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Container>; rel="type"` + `, <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else { | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return link; | ||
} | ||
} // THE END! |
@@ -7,25 +7,14 @@ "use strict"; | ||
exports.default = void 0; | ||
var _examineRequest = require("./examineRequest.js"); | ||
var _examineRequestedItem = require("./examineRequestedItem.js"); | ||
var _handleRequest = require("./handleRequest.js"); | ||
var _performRequestedMethod = _interopRequireDefault(require("./performRequestedMethod.js")); | ||
var _handleResponse = require("./handleResponse.js"); | ||
var _utils = require("./utils/utils.js"); | ||
var _container = _interopRequireDefault(require("./utils/container.js")); | ||
var _restPatch = _interopRequireDefault(require("./utils/rest-patch.js")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
class SolidRest { | ||
constructor(options) { | ||
options = options || {}; | ||
if (!options.plugin) { | ||
@@ -35,3 +24,2 @@ console.log(`You must specify a plugin storage handler!`); | ||
} | ||
this.storage = options.plugin; | ||
@@ -54,3 +42,2 @@ this.handleRequest = _handleRequest.handleRequest.bind(this); | ||
} | ||
async fetch(uri, options = {}) { | ||
@@ -60,3 +47,2 @@ let response = await this.handleRequest(uri, options); | ||
} | ||
async login(options) { | ||
@@ -70,21 +56,15 @@ options = { | ||
} | ||
async itemExists(pathname) { | ||
return await this.perform('ITEM_EXISTS', pathname); | ||
} | ||
isPatchConflictError(response) { | ||
if (response === 400) return true; | ||
} | ||
isAccessError(response) { | ||
if (response === 401) return true; | ||
} | ||
/* =========================================================== */ | ||
/* REST METHODS */ | ||
/* =========================================================== */ | ||
async GET(url) { | ||
@@ -95,3 +75,2 @@ return await this.fetch(url, { | ||
} | ||
async HEAD(url) { | ||
@@ -102,3 +81,2 @@ return await this.fetch(url, { | ||
} | ||
async EXISTS(url) { | ||
@@ -114,3 +92,2 @@ try { | ||
} | ||
async PUT(url, text, ctype) { | ||
@@ -126,3 +103,2 @@ ctype = ctype || 'text/turtle'; | ||
} | ||
async PATCH(url, patchContent, patchContentType) { | ||
@@ -140,3 +116,2 @@ patchContentType = patchContent || "text/n3"; | ||
} | ||
async DELETE(url) { | ||
@@ -147,3 +122,2 @@ return await this.fetch(url, { | ||
} | ||
async POST(parent, item, content, link) { | ||
@@ -160,3 +134,2 @@ return await this.fetch(parent, { | ||
} | ||
async postFile(parent, file, content) { | ||
@@ -166,3 +139,2 @@ let link = '<http://www.w3.org/ns/ldp#Resource>; rel="type"'; | ||
} | ||
async postFolder(parent, folder) { | ||
@@ -172,6 +144,3 @@ let link = '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"'; | ||
} | ||
} // THE END | ||
exports.default = SolidRest; |
@@ -7,3 +7,2 @@ "use strict"; | ||
exports.default = perform; | ||
async function perform(method, pathname, content, ctype) { | ||
@@ -20,3 +19,2 @@ this.request = this.requestObj; | ||
}; | ||
switch (method) { | ||
@@ -26,3 +24,2 @@ case 'STORAGE_NAME': | ||
break; | ||
case 'ITEM_EXISTS': | ||
@@ -32,7 +29,5 @@ pathname = pathname.replace('file://', ''); | ||
break; | ||
case 'LOGIN': | ||
return await this.storage.login(this.request.loginoptions); | ||
break; | ||
case 'ITEM_TYPE': | ||
@@ -42,20 +37,15 @@ // Container/Resource | ||
break; | ||
case 'GET_CONTENT_TYPE': | ||
return await this.storage.getContentType(pathname); // return await this.storage.getContentType(pathname).bind(this.storage); | ||
return await this.storage.getContentType(pathname); | ||
// return await this.storage.getContentType(pathname).bind(this.storage); | ||
break; | ||
case 'GET_PATH_HANDLER': | ||
return await this.storage.getPathHandler(pathname); | ||
break; | ||
case 'GET_ITEM_INFO': | ||
return await this.storage.getItemInfo(pathname, this.request); | ||
break; | ||
case 'GET_FILES': | ||
return await this.storage.getContainer(pathname); | ||
break; | ||
case 'DELETE': | ||
@@ -69,8 +59,5 @@ if (this.item.isContainer) { | ||
} | ||
break; | ||
case 'DELETE_AUX_RESOURCES': | ||
const links = (await this.getAuxResources(pathname)) || []; | ||
try { | ||
@@ -85,18 +72,13 @@ links.map(async link => { | ||
} | ||
return 200; | ||
break; | ||
case 'CREATE_INTERMEDIATE_CONTAINERS': | ||
return (await this.storage.makeContainers(pathname)) || 1; | ||
break; | ||
case 'GET': | ||
if (this.item.isContainer) { | ||
let files = await this.storage.getContainer(pathname); | ||
if (files.headers) { | ||
return files; | ||
} | ||
return await this.containerAsTurtle(pathname, files, this.request.typewanted, this); | ||
@@ -106,7 +88,5 @@ } else { | ||
if (!thing) return false; | ||
if (thing.headers) { | ||
return thing; | ||
} | ||
this.response.body = thing; | ||
@@ -116,5 +96,3 @@ this.response.headers.status = 200; | ||
} | ||
break; | ||
case 'OPTIONS': | ||
@@ -124,7 +102,5 @@ case 'HEAD': | ||
break; | ||
case 'PUT': | ||
content = content || this.request.body; | ||
ctype = ctype || this.item.contentType || ""; // console.log('content for put',content); | ||
let x = await this.storage.putResource(pathname, content, ctype); // console.log('response from put',x); | ||
@@ -135,3 +111,2 @@ | ||
break; | ||
case 'FULL_PUT': | ||
@@ -144,3 +119,2 @@ let success = await this.storage.makeContainers(pathname); | ||
break; | ||
case 'POST': | ||
@@ -156,5 +130,3 @@ if (this.request.headers.link.match("Container")) { | ||
} | ||
break; | ||
case 'PATCH': | ||
@@ -172,13 +144,11 @@ const contentType = this.item.contentType; | ||
if (!exists) await this.perform('FULL_PUT', pathname, "", ctype); | ||
; // 415 patchOnNonTurtle is handled already in handleRequest.js | ||
; | ||
// 415 patchOnNonTurtle is handled already in handleRequest.js | ||
let oldContent = await this.storage.getResource(pathname); | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; // if (!oldContent) return false; | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; | ||
// if (!oldContent) return false; | ||
oldContent = typeof oldContent === 'string' ? oldContent : oldContent.toString(); | ||
let newContent, patchStatus; | ||
try { | ||
[patchStatus, newContent] = await this.patch.patchContent(oldContent, contentType, this.request); | ||
if (patchStatus !== 200) { | ||
@@ -196,7 +166,7 @@ return { | ||
}; | ||
} // const status = await this.storage.makeContainers(pathname); | ||
} | ||
// const status = await this.storage.makeContainers(pathname); | ||
// if (!status) return false; | ||
// let putStatus = await this.storage.putResource(pathname, this.request.bod); | ||
let putStatus = await this.storage.putResource(pathname, newContent); | ||
@@ -203,0 +173,0 @@ putStatus = putStatus && putStatus.body ? putStatus.body : putStatus; |
@@ -7,11 +7,9 @@ "use strict"; | ||
exports.default = containerAsTurtle; | ||
// import libPath from 'path'; | ||
// import libPath from 'path'; | ||
async function containerAsTurtle(pathname, contentsArray, typeWanted, self) { | ||
const pathSep = self.pathSep; | ||
function basename(path) { | ||
return path.substr(path.lastIndexOf(self.pathSep) + 1); | ||
} | ||
let filenames = contentsArray.filter(item => { | ||
@@ -30,7 +28,6 @@ if (item.path && !item.path.endsWith('.acl') && !item.path.endsWith('.meta')) { | ||
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. | ||
<> a ldp:BasicContainer, ldp:Container | ||
`; | ||
<> a ldp:BasicContainer, ldp:Container`; | ||
if (filenames.length) { | ||
str = str + "; ldp:contains\n"; | ||
str = str + ";\n ldp:contains\n"; // alain | ||
@@ -42,3 +39,2 @@ for (var i = 0; i < filenames.length; i++) { | ||
fn = basename(fn); // contained resources are relative to folder | ||
if (filenames[i].isContainer && !fn.endsWith("/")) fn = fn + "/"; | ||
@@ -48,3 +44,2 @@ str = str + ` <${fn}>,\n`; | ||
let ctype, size, mtime, modified; | ||
if (self && self.storage.getMetadata) { | ||
@@ -60,19 +55,21 @@ try { | ||
} | ||
} else if (filenames[i].metadata) { | ||
size = filenames[i].metadata.size; | ||
mtime = filenames[i].metadata.mtimeMs; | ||
modified = new Date(mtime).toISOString(); | ||
} | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; // REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; | ||
// REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype.replace(/;.*/, ''); | ||
ftype = filenames[i].isContainer ? "ldp:Container; a ldp:BasicContainer; a ldp:Resource" : "ldp:Resource"; | ||
str2 = str2 + `<${fn}> a ${ftype}.\n`; | ||
if (ctype) str2 = str2 + `<${fn}> a <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>.\n`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
str2 = str2 + `<${fn}> a ${ftype}`; | ||
if (ctype && !filenames[i].isContainer) | ||
// no media-type for Container | ||
str2 = str2 + `, <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
if (size) { | ||
str2 = str2 + `<${fn}> stat:size ${size}; stat:mtime ${mtime}; dct:"${modified}"^^xsd:dateTime.\n`; | ||
str2 = str2 + `;\n stat:size ${size};\n stat:mtime ${mtime};\n dct:modified "${modified}"^^xsd:dateTime.\n`; | ||
} | ||
} | ||
str = str.replace(/,\n$/, ""); | ||
} | ||
str = str + `.\n` + str2; // str = _makeStream(str); | ||
@@ -79,0 +76,0 @@ |
@@ -6,4 +6,4 @@ "use strict"; | ||
}); | ||
exports.acl_content = exports.private_content = exports.public_content = exports.prefs_content = exports.profile_content = void 0; | ||
const profile_content = `@prefix : <#>. | ||
exports.public_content = exports.profile_content = exports.private_content = exports.prefs_content = exports.acl_content = void 0; | ||
const profile_content = exports.profile_content = `@prefix : <#>. | ||
@prefix jef: <../>. | ||
@@ -41,4 +41,3 @@ @prefix ldp: <http://www.w3.org/ns/ldp#>. | ||
`; | ||
exports.profile_content = profile_content; | ||
const prefs_content = `@prefix : <#>. | ||
const prefs_content = exports.prefs_content = `@prefix : <#>. | ||
@prefix solid: <http://www.w3.org/ns/solid/terms#>. | ||
@@ -57,4 +56,3 @@ @prefix sp: <http://www.w3.org/ns/pim/space#>. | ||
`; | ||
exports.prefs_content = prefs_content; | ||
const public_content = `@prefix : <#>. | ||
const public_content = exports.public_content = `@prefix : <#>. | ||
@prefix solid: <https://www.w3.org/ns/solid/terms#>. | ||
@@ -72,4 +70,3 @@ @prefix terms: <http://purl.org/dc/terms/>. | ||
`; | ||
exports.public_content = public_content; | ||
const private_content = ` | ||
const private_content = exports.private_content = ` | ||
@prefix solid: <https://www.w3.org/ns/solid/terms#>. | ||
@@ -80,4 +77,3 @@ <> | ||
`; | ||
exports.private_content = private_content; | ||
const acl_content = `@prefix acl: <http://www.w3.org/ns/auth/acl#>. | ||
const acl_content = exports.acl_content = `@prefix acl: <http://www.w3.org/ns/auth/acl#>. | ||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. | ||
@@ -106,4 +102,2 @@ | ||
`; | ||
/* ENDS */ | ||
exports.acl_content = acl_content; | ||
/* ENDS */ |
@@ -15,3 +15,2 @@ "use strict"; | ||
}; | ||
class RestPatch { | ||
@@ -21,3 +20,2 @@ constructor(passedRDF) { | ||
} | ||
async patchContent(content, contentType, request) { | ||
@@ -34,10 +32,7 @@ const url = request.url; | ||
const parsePatch = PATCH_PARSERS[patch.contentType]; | ||
if (!parsePatch) { | ||
return [415, `415 Unsupported patch content type: ${patch.contentType}`]; | ||
} // Parse the patch document and verify permissions | ||
} | ||
// Parse the patch document and verify permissions | ||
const patchUri = `${url}#patch`; | ||
try { | ||
@@ -50,3 +45,2 @@ const patchObject = await parsePatch(url, patchUri, patch.text); | ||
*/ | ||
let insertStmts = patch.text.match(/INSERT/g); | ||
@@ -60,10 +54,9 @@ if (insertStmts && insertStmts.length > 1) return [400, "can not have multiple INSERT statements in a patch"]; | ||
} | ||
} // PARSE ORIGINAL DOCUMENT | ||
} | ||
// PARSE ORIGINAL DOCUMENT | ||
// | ||
async readGraph(fileContents, resource) { | ||
const graph = $rdf.graph(); | ||
if (!fileContents.length) return graph; | ||
try { | ||
@@ -74,8 +67,7 @@ $rdf.parse(fileContents, graph, resource.url, resource.contentType); | ||
} | ||
return graph; | ||
} | ||
return graph; | ||
} // APPLY PATCH | ||
// APPLY PATCH | ||
// | ||
async applyPatch(patchObject, graph, url) { | ||
@@ -85,14 +77,11 @@ return new Promise((resolve, reject) => graph.applyPatch(patchObject, graph.sym(url), err => { | ||
const message = err.message || err; // returns string at the moment | ||
return reject(new Error(`409 : The patch could not be applied. ${message}`)); // is this correct : not tested | ||
} | ||
resolve(graph); | ||
})); | ||
} // serialize graph to turtle | ||
} | ||
// serialize graph to turtle | ||
async writeGraph(graph, resource) { | ||
const resourceSym = graph.sym(resource.url); | ||
try { | ||
@@ -104,19 +93,14 @@ const serialized = $rdf.serialize(resourceSym, graph, resource.url, resource.contentType); | ||
} | ||
} // Creates a hash of the given text | ||
} | ||
// Creates a hash of the given text | ||
hash(text) { | ||
return crypto.createHash('md5').update(text).digest('hex'); | ||
} | ||
} // END OF CLASS RestPatch | ||
} // END OF CLASS RestPatch | ||
// PARSE SPARQL | ||
// | ||
exports.default = RestPatch; | ||
async function parsePatchSparql(targetURI, patchURI, patchText) { | ||
const baseURI = patchURI.replace(/#.*/, ''); | ||
try { | ||
@@ -127,9 +111,8 @@ return $rdf.sparqlUpdateParser(patchText, $rdf.graph(), baseURI); | ||
} | ||
} // PARSE N3 | ||
} | ||
// PARSE N3 | ||
// | ||
async function parsePatchN3(targetURI, patchURI, patchText) { | ||
const patchGraph = $rdf.graph(); | ||
try { | ||
@@ -140,5 +123,3 @@ $rdf.parse(patchText, patchGraph, patchURI, 'text/n3'); | ||
} | ||
let firstResult; | ||
try { | ||
@@ -165,3 +146,2 @@ firstResult = await queryForFirstResult(patchGraph, `${PREFIXES} | ||
} | ||
const { | ||
@@ -172,7 +152,6 @@ '?insert': insert, | ||
} = firstResult; | ||
if (!insert && !deleted) { | ||
return [400, 'Patch should at least contain inserts or deletes.']; // throw error(400, 'Patch should at least contain inserts or deletes.') | ||
return [400, 'Patch should at least contain inserts or deletes.']; | ||
// throw error(400, 'Patch should at least contain inserts or deletes.') | ||
} | ||
return { | ||
@@ -183,6 +162,6 @@ insert, | ||
}; | ||
} // EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
} | ||
// EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
// | ||
function queryForFirstResult(store, sparql) { | ||
@@ -193,4 +172,5 @@ return new Promise((resolve, reject) => { | ||
return ['409 : No results.']; | ||
}); // TODO check status | ||
}); | ||
// TODO check status | ||
}); | ||
} |
@@ -7,22 +7,15 @@ "use strict"; | ||
exports.createServerlessPod = createServerlessPod; | ||
exports.generateRandomSlug = generateRandomSlug; | ||
exports.getAuxResources = getAuxResources; | ||
exports.getContentType = getContentType; | ||
exports.isAuxResource = isAuxResource; | ||
exports.getAuxResources = getAuxResources; | ||
exports.generateRandomSlug = generateRandomSlug; | ||
exports.linksExt = exports.linkExt = void 0; | ||
var _uuid = require("uuid"); | ||
var pod = _interopRequireWildcard(require("./createServerlessPod.js")); | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } | ||
// import { contentType as contentTypeLookup } from 'mime-types'; | ||
const linkExt = ['.acl', '.meta']; | ||
exports.linkExt = linkExt; | ||
const linksExt = linkExt.concat('.meta.acl'); | ||
exports.linksExt = linksExt; | ||
const linkExt = exports.linkExt = ['.acl', '.meta']; | ||
const linksExt = exports.linksExt = linkExt.concat('.meta.acl'); | ||
async function createServerlessPod(base) { | ||
@@ -42,6 +35,4 @@ console.log(`Creating pod at <${base}>`); | ||
} | ||
async function getContentType(path, type) { | ||
let ext = this.getExtension(path); | ||
if (!ext || ext === '.ttl' || ext === '.acl' || ext === '.meta' || type === "Container") { | ||
@@ -55,7 +46,6 @@ return 'text/turtle'; | ||
} | ||
function isAuxResource(o) { | ||
return linkExt.find(ext => this.getExtension(o) === ext); // return linkExt.find(ext => o.extension === ext); | ||
return linkExt.find(ext => this.getExtension(o) === ext); | ||
// return linkExt.find(ext => o.extension === ext); | ||
} | ||
async function getAuxResources(pathname) { | ||
@@ -68,12 +58,9 @@ if (pathname.endsWith('.acl')) return []; | ||
} | ||
async function generateRandomSlug(pathname, slug = (0, _uuid.v1)()) { | ||
let requestUrl = this.mungePath(pathname, slug); | ||
if (this.item.isContainer && !this.request.url.endsWith(this.pathSep)) requestUrl = requestUrl + this.pathSep; | ||
if (await this.perform('ITEM_EXISTS', requestUrl)) { | ||
slug = `${(0, _uuid.v1)()}-${slug}`; | ||
} | ||
return this.mungePath(pathname, slug); | ||
} |
@@ -8,3 +8,2 @@ import { Url as URL } from "url"; | ||
request.body = request.body || ""; | ||
if (!validUrl(uri)) { | ||
@@ -18,3 +17,2 @@ request.url = null; | ||
} | ||
if (request.url && request.url.endsWith('.dummy')) { | ||
@@ -25,3 +23,2 @@ // rdflib does this !!! | ||
} | ||
return request; | ||
@@ -35,3 +32,2 @@ } | ||
let newOpts = {}; | ||
for (var o in opts) { | ||
@@ -42,6 +38,4 @@ if (o === 'host') { | ||
} | ||
return newOpts; | ||
} | ||
const validUrl = s => { | ||
@@ -59,5 +53,4 @@ try { | ||
function normalizeRequestMethod(method) { | ||
return method ? method.toUpperCase() : 'GET'; | ||
} |
@@ -7,3 +7,2 @@ //import libPath from "path"; | ||
pathHandler = await this.perform('GET_PATH_HANDLER', uri); | ||
if (uri.startsWith('file')) { | ||
@@ -16,3 +15,2 @@ url = Url.format(request.url); | ||
} | ||
const item = await this.perform('GET_ITEM_INFO', pname, request); | ||
@@ -25,3 +23,2 @@ item.mode = item.mode ? item.mode : { | ||
item.pathname = pname; | ||
if (request.method === 'DELETE' && item.isContainer) { | ||
@@ -35,3 +32,2 @@ let files = await this.perform('GET_FILES', item.pathname); | ||
} | ||
this.getExtension = path => { | ||
@@ -42,6 +38,4 @@ path = path || this.item.pathname || ""; | ||
}; | ||
this.pathSep = pathHandler.sep; | ||
this.basename = pathHandler.extname; | ||
this.mungePath = (pathname, slug, options) => { | ||
@@ -52,3 +46,2 @@ pathname = pathHandler.join(pathname, slug); | ||
}; | ||
pname = request.method === "POST" ? this.mungePath(item.pathname, request.slug) : item.pathname; | ||
@@ -59,5 +52,6 @@ item.extension = this.getExtension(pname); | ||
item.isAcl = pname.match(/\.acl/); // TBD use LinkExt | ||
//item.isAuxResource = item.isAcl || this.extension === '.meta'; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
/* | ||
@@ -64,0 +58,0 @@ let conflict |
@@ -34,6 +34,4 @@ const methods = { | ||
const request = this.requestObj = await this.getRequest(uri, originalRequest); // | ||
const item = this.item = await this.getItem(uri, request); // | ||
// Errors we find in the request | ||
if (!request.url || !request.method) return 400; | ||
@@ -44,11 +42,9 @@ if (request.slug.endsWith('/')) return 400; | ||
if (request.method === 'PATCH' && !this.patch) return 405; | ||
if (request.method === 'POST' && !request.headers.link) return 400; // Errors we find by comparing the request & the itemRequested | ||
if (request.method === 'POST' && !request.headers.link) return 400; | ||
// Errors we find by comparing the request & the itemRequested | ||
if (item.isContainer && !item.contentType) item.contentType = "text/turtle"; | ||
if (item.folderFileConfusion) return 400; // can't have both /foo and /foo/ | ||
if (item.patchOnNonRdf) return 400; | ||
if (item.mode.write) item.mode.append = true; | ||
const method = methods[request.method]; | ||
if (item.isAuxResource) { | ||
@@ -58,3 +54,2 @@ if (item.isAcl) method.requiresControl = true; | ||
} | ||
if (!method) console.log(55, request.method); | ||
@@ -64,3 +59,2 @@ if (!method) return 409; | ||
if (method.requiresRead && !item.mode.read || method.requiresAppend && !item.mode.append || method.requiresWrite && !item.mode.write || method.requiresControl && !item.mode.control) return 401; | ||
if (method.requiresContentType && !request.headers['content-type']) { | ||
@@ -70,3 +64,2 @@ // console.log(request.method, "No Content Type"); | ||
} | ||
if (request.method === 'POST') { | ||
@@ -77,3 +70,2 @@ this.item.pathname = await this.generateRandomSlug(this.item.pathname, request.slug); | ||
if (request.method === 'PUT' || request.method === 'POST' || request.method === 'PATCH') { | ||
@@ -84,8 +76,5 @@ // if (item.isContainer) return 405; | ||
} | ||
let response = await this.perform(request.method); | ||
if (!response && request.method === 'DELETE' && item.isContainer) { | ||
let stillExists = await this.perform('ITEM_EXISTS', this.item.pathname); | ||
if (stillExists) { | ||
@@ -95,4 +84,3 @@ return 409; | ||
} | ||
return response; | ||
} // ENDS |
@@ -25,3 +25,2 @@ /* | ||
let wrapHeaders = true; // {headers} instead of headers for Response | ||
let method = originalRequest.method || this.request.method || "GET"; | ||
@@ -39,3 +38,2 @@ let finalResponse = { | ||
*/ | ||
if (typeof response === 'number') { | ||
@@ -62,22 +60,23 @@ wrapHeaders = false; | ||
if (method.match(/(PUT)/) && finalResponse.headers.status == 200) { | ||
finalResponse.headers.status = 201; | ||
} | ||
if (method.match(/(DELETE|GET|HEAD)/) && finalResponse.headers.status == 201) { | ||
finalResponse.headers.status = 200; | ||
} | ||
let headers = {}; | ||
const request = this.requestObj; | ||
const item = this.item; | ||
const pathname = item.pathname; // const fn = libPath.basename(pathname); | ||
const pathname = item.pathname; | ||
// const fn = libPath.basename(pathname); | ||
const fn = pathname.replace(/.*\//, ''); | ||
headers['vary'] = 'accept,authorization,origin'; | ||
headers['access-control-expose-headers'] = 'accept-patch,accept-post,accept-put,allow,content-range,etag,last-modified,link,location,updates-via,wac-allow,www-authenticate'; | ||
headers['content-type'] = this.item.contentType; // CONTENT-TYPE | ||
headers.link = headers.link || createLinkHeader(item); // LINK | ||
const storageHeader = item.pathname === '/' ? ', <http://www.w3.org/ns/pim/space#Storage>; rel="type"' : ''; | ||
headers.link = headers.link || createLinkHeader(item) + storageHeader; // LINK | ||
headers.allow = createAllowHeader(this.patch, this.item.mode); // ALLOW | ||
headers.allow = createAllowHeader(item.pathname); // ALLOW | ||
@@ -90,6 +89,6 @@ headers['wac-allow'] = createWacHeader(this.item.mode); // WAC-ALLOW | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; // NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; | ||
// NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
headers.url = pathname; | ||
if (method === "POST") { | ||
@@ -107,15 +106,14 @@ headers.url = this.request.url; | ||
} | ||
/* if (this.patch) { // ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} */ | ||
if (this.patch) { | ||
// ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
let body = finalResponse.body || this.response.body || ""; // Now we merge headers we created with response headers, prefering response | ||
Object.assign(headers, finalResponse.headers); //alert(finalResponse.headers.status) | ||
Object.assign(headers, finalResponse.headers); | ||
//alert(finalResponse.headers.status) | ||
headers.status = finalResponse.headers.status || this.response.headers.status || 500; | ||
let $rdf = typeof window != "undefined" && window.$rdf ? window.$rdf : typeof global != "undefined" && global.$rdf ? global.$rdf : null; | ||
/* | ||
@@ -146,12 +144,18 @@ async function serialize(uri,body,informat,outformat){ | ||
*/ | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers = createAcceptHeader(request, headers); // ACCEPT | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers.etag = `W/"${uuid()}"`; | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; // Now we create & return the Response object | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; | ||
// TODO (?) last-modified | ||
// Now we create & return the Response object | ||
for (var h of Object.keys(headers)) { | ||
if (!headers[h]) delete headers[h]; | ||
} | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; // headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// if(!headers.location.match(/^file:/)) headers.location = "file://"+headers.location; | ||
@@ -161,3 +165,2 @@ | ||
body = ""; | ||
for (let k of Object.keys(headers)) { | ||
@@ -167,3 +170,2 @@ body = body + `${k}:${headers[k]}\n`; | ||
} | ||
if (originalRequest.plainResponse) { | ||
@@ -180,3 +182,2 @@ // from a server that wants to munge | ||
} | ||
wrapHeaders = true; | ||
@@ -191,3 +192,2 @@ headers = wrapHeaders ? { | ||
let responseObject; | ||
try { | ||
@@ -200,3 +200,2 @@ responseObject = new Response(body, headers, { | ||
} | ||
return responseObject; | ||
@@ -212,7 +211,26 @@ } // end of handleResponse method | ||
} | ||
function createAllowHeader(patch, mode) { | ||
return 'OPTIONS,HEAD' + (mode.read ? ',GET' : '') + (mode.write ? ',POST,PUT,DELETE' : '') + (mode.write && patch ? ',PATCH' : ''); | ||
function createAllowHeader(requestPath) { | ||
// root/ root/.acl can't be deleted | ||
let del = requestPath === '/' || requestPath === '/.acl' ? '' : ',DELETE'; | ||
// no PATCH on Container | ||
if (requestPath.endsWith('/')) return 'OPTIONS,HEAD,GET,POST,PUT' + del; | ||
// no POST on Document | ||
else return 'OPTIONS,HEAD,GET,PATCH,PUT' + del; | ||
} | ||
function createAcceptHeader(request, headers) { | ||
const status = headers.status; | ||
// no Accept header | ||
if (request.method.match(/DELETE/) || status >= 500 || status.toString().match(/401|403/)) return headers; | ||
// Accept headers on container | ||
if (request.url.endsWith('/')) { | ||
if (status === 404) headers['accept-put'] = ['*/*']; | ||
headers['accept-post'] = ['*/*']; | ||
} else { | ||
// Accept headers on document | ||
headers['accept-put'] = ['*/*']; | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
return headers; | ||
} | ||
function createLinkHeader(item) { | ||
@@ -223,12 +241,13 @@ let isContainer = item.isContainer; | ||
let ext = item.extension; | ||
if (ext === '.acl') // .acl not controlledBy or describedBy anything | ||
if (ext === '.acl') | ||
// .acl not controlledBy or describedBy anything | ||
return `<http://www.w3.org/ns/ldp#Resource>; rel="type"`;else if (ext === '.meta') { | ||
return `<${fn}.acl>; rel="acl",` // .meta controlledBy .meta.acl | ||
+ `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<${fn}.acl>; rel="acl"` // .meta controlledBy .meta.acl | ||
+ `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else if (isContainer) { | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Container>; rel="type",` + `<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Container>; rel="type"` + `, <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else { | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return link; | ||
} | ||
} // THE END! |
@@ -12,3 +12,2 @@ import { getRequest } from './examineRequest.js'; | ||
options = options || {}; | ||
if (!options.plugin) { | ||
@@ -18,3 +17,2 @@ console.log(`You must specify a plugin storage handler!`); | ||
} | ||
this.storage = options.plugin; | ||
@@ -37,3 +35,2 @@ this.handleRequest = handleRequest.bind(this); | ||
} | ||
async fetch(uri, options = {}) { | ||
@@ -43,3 +40,2 @@ let response = await this.handleRequest(uri, options); | ||
} | ||
async login(options) { | ||
@@ -53,21 +49,15 @@ options = { | ||
} | ||
async itemExists(pathname) { | ||
return await this.perform('ITEM_EXISTS', pathname); | ||
} | ||
isPatchConflictError(response) { | ||
if (response === 400) return true; | ||
} | ||
isAccessError(response) { | ||
if (response === 401) return true; | ||
} | ||
/* =========================================================== */ | ||
/* REST METHODS */ | ||
/* =========================================================== */ | ||
async GET(url) { | ||
@@ -78,3 +68,2 @@ return await this.fetch(url, { | ||
} | ||
async HEAD(url) { | ||
@@ -85,3 +74,2 @@ return await this.fetch(url, { | ||
} | ||
async EXISTS(url) { | ||
@@ -97,3 +85,2 @@ try { | ||
} | ||
async PUT(url, text, ctype) { | ||
@@ -109,3 +96,2 @@ ctype = ctype || 'text/turtle'; | ||
} | ||
async PATCH(url, patchContent, patchContentType) { | ||
@@ -123,3 +109,2 @@ patchContentType = patchContent || "text/n3"; | ||
} | ||
async DELETE(url) { | ||
@@ -130,3 +115,2 @@ return await this.fetch(url, { | ||
} | ||
async POST(parent, item, content, link) { | ||
@@ -143,3 +127,2 @@ return await this.fetch(parent, { | ||
} | ||
async postFile(parent, file, content) { | ||
@@ -149,3 +132,2 @@ let link = '<http://www.w3.org/ns/ldp#Resource>; rel="type"'; | ||
} | ||
async postFolder(parent, folder) { | ||
@@ -155,3 +137,2 @@ let link = '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"'; | ||
} | ||
} // THE END |
@@ -12,3 +12,2 @@ export default async function perform(method, pathname, content, ctype) { | ||
}; | ||
switch (method) { | ||
@@ -18,3 +17,2 @@ case 'STORAGE_NAME': | ||
break; | ||
case 'ITEM_EXISTS': | ||
@@ -24,7 +22,5 @@ pathname = pathname.replace('file://', ''); | ||
break; | ||
case 'LOGIN': | ||
return await this.storage.login(this.request.loginoptions); | ||
break; | ||
case 'ITEM_TYPE': | ||
@@ -34,20 +30,15 @@ // Container/Resource | ||
break; | ||
case 'GET_CONTENT_TYPE': | ||
return await this.storage.getContentType(pathname); // return await this.storage.getContentType(pathname).bind(this.storage); | ||
return await this.storage.getContentType(pathname); | ||
// return await this.storage.getContentType(pathname).bind(this.storage); | ||
break; | ||
case 'GET_PATH_HANDLER': | ||
return await this.storage.getPathHandler(pathname); | ||
break; | ||
case 'GET_ITEM_INFO': | ||
return await this.storage.getItemInfo(pathname, this.request); | ||
break; | ||
case 'GET_FILES': | ||
return await this.storage.getContainer(pathname); | ||
break; | ||
case 'DELETE': | ||
@@ -61,8 +52,5 @@ if (this.item.isContainer) { | ||
} | ||
break; | ||
case 'DELETE_AUX_RESOURCES': | ||
const links = (await this.getAuxResources(pathname)) || []; | ||
try { | ||
@@ -77,18 +65,13 @@ links.map(async link => { | ||
} | ||
return 200; | ||
break; | ||
case 'CREATE_INTERMEDIATE_CONTAINERS': | ||
return (await this.storage.makeContainers(pathname)) || 1; | ||
break; | ||
case 'GET': | ||
if (this.item.isContainer) { | ||
let files = await this.storage.getContainer(pathname); | ||
if (files.headers) { | ||
return files; | ||
} | ||
return await this.containerAsTurtle(pathname, files, this.request.typewanted, this); | ||
@@ -98,7 +81,5 @@ } else { | ||
if (!thing) return false; | ||
if (thing.headers) { | ||
return thing; | ||
} | ||
this.response.body = thing; | ||
@@ -108,5 +89,3 @@ this.response.headers.status = 200; | ||
} | ||
break; | ||
case 'OPTIONS': | ||
@@ -116,7 +95,5 @@ case 'HEAD': | ||
break; | ||
case 'PUT': | ||
content = content || this.request.body; | ||
ctype = ctype || this.item.contentType || ""; // console.log('content for put',content); | ||
let x = await this.storage.putResource(pathname, content, ctype); // console.log('response from put',x); | ||
@@ -127,3 +104,2 @@ | ||
break; | ||
case 'FULL_PUT': | ||
@@ -136,3 +112,2 @@ let success = await this.storage.makeContainers(pathname); | ||
break; | ||
case 'POST': | ||
@@ -148,5 +123,3 @@ if (this.request.headers.link.match("Container")) { | ||
} | ||
break; | ||
case 'PATCH': | ||
@@ -164,13 +137,11 @@ const contentType = this.item.contentType; | ||
if (!exists) await this.perform('FULL_PUT', pathname, "", ctype); | ||
; // 415 patchOnNonTurtle is handled already in handleRequest.js | ||
; | ||
// 415 patchOnNonTurtle is handled already in handleRequest.js | ||
let oldContent = await this.storage.getResource(pathname); | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; // if (!oldContent) return false; | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; | ||
// if (!oldContent) return false; | ||
oldContent = typeof oldContent === 'string' ? oldContent : oldContent.toString(); | ||
let newContent, patchStatus; | ||
try { | ||
[patchStatus, newContent] = await this.patch.patchContent(oldContent, contentType, this.request); | ||
if (patchStatus !== 200) { | ||
@@ -188,7 +159,7 @@ return { | ||
}; | ||
} // const status = await this.storage.makeContainers(pathname); | ||
} | ||
// const status = await this.storage.makeContainers(pathname); | ||
// if (!status) return false; | ||
// let putStatus = await this.storage.putResource(pathname, this.request.bod); | ||
let putStatus = await this.storage.putResource(pathname, newContent); | ||
@@ -195,0 +166,0 @@ putStatus = putStatus && putStatus.body ? putStatus.body : putStatus; |
// import libPath from 'path'; | ||
export default async function containerAsTurtle(pathname, contentsArray, typeWanted, self) { | ||
const pathSep = self.pathSep; | ||
function basename(path) { | ||
return path.substr(path.lastIndexOf(self.pathSep) + 1); | ||
} | ||
let filenames = contentsArray.filter(item => { | ||
@@ -22,7 +21,6 @@ if (item.path && !item.path.endsWith('.acl') && !item.path.endsWith('.meta')) { | ||
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. | ||
<> a ldp:BasicContainer, ldp:Container | ||
`; | ||
<> a ldp:BasicContainer, ldp:Container`; | ||
if (filenames.length) { | ||
str = str + "; ldp:contains\n"; | ||
str = str + ";\n ldp:contains\n"; // alain | ||
@@ -34,3 +32,2 @@ for (var i = 0; i < filenames.length; i++) { | ||
fn = basename(fn); // contained resources are relative to folder | ||
if (filenames[i].isContainer && !fn.endsWith("/")) fn = fn + "/"; | ||
@@ -40,3 +37,2 @@ str = str + ` <${fn}>,\n`; | ||
let ctype, size, mtime, modified; | ||
if (self && self.storage.getMetadata) { | ||
@@ -52,19 +48,21 @@ try { | ||
} | ||
} else if (filenames[i].metadata) { | ||
size = filenames[i].metadata.size; | ||
mtime = filenames[i].metadata.mtimeMs; | ||
modified = new Date(mtime).toISOString(); | ||
} | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; // REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; | ||
// REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype.replace(/;.*/, ''); | ||
ftype = filenames[i].isContainer ? "ldp:Container; a ldp:BasicContainer; a ldp:Resource" : "ldp:Resource"; | ||
str2 = str2 + `<${fn}> a ${ftype}.\n`; | ||
if (ctype) str2 = str2 + `<${fn}> a <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>.\n`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
str2 = str2 + `<${fn}> a ${ftype}`; | ||
if (ctype && !filenames[i].isContainer) | ||
// no media-type for Container | ||
str2 = str2 + `, <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
if (size) { | ||
str2 = str2 + `<${fn}> stat:size ${size}; stat:mtime ${mtime}; dct:"${modified}"^^xsd:dateTime.\n`; | ||
str2 = str2 + `;\n stat:size ${size};\n stat:mtime ${mtime};\n dct:modified "${modified}"^^xsd:dateTime.\n`; | ||
} | ||
} | ||
str = str.replace(/,\n$/, ""); | ||
} | ||
str = str + `.\n` + str2; // str = _makeStream(str); | ||
@@ -71,0 +69,0 @@ |
@@ -13,3 +13,2 @@ let $rdf; //import crypto from 'crypto' TODO may be | ||
} | ||
async patchContent(content, contentType, request) { | ||
@@ -26,10 +25,7 @@ const url = request.url; | ||
const parsePatch = PATCH_PARSERS[patch.contentType]; | ||
if (!parsePatch) { | ||
return [415, `415 Unsupported patch content type: ${patch.contentType}`]; | ||
} // Parse the patch document and verify permissions | ||
} | ||
// Parse the patch document and verify permissions | ||
const patchUri = `${url}#patch`; | ||
try { | ||
@@ -42,3 +38,2 @@ const patchObject = await parsePatch(url, patchUri, patch.text); | ||
*/ | ||
let insertStmts = patch.text.match(/INSERT/g); | ||
@@ -52,10 +47,9 @@ if (insertStmts && insertStmts.length > 1) return [400, "can not have multiple INSERT statements in a patch"]; | ||
} | ||
} // PARSE ORIGINAL DOCUMENT | ||
} | ||
// PARSE ORIGINAL DOCUMENT | ||
// | ||
async readGraph(fileContents, resource) { | ||
const graph = $rdf.graph(); | ||
if (!fileContents.length) return graph; | ||
try { | ||
@@ -66,8 +60,7 @@ $rdf.parse(fileContents, graph, resource.url, resource.contentType); | ||
} | ||
return graph; | ||
} | ||
return graph; | ||
} // APPLY PATCH | ||
// APPLY PATCH | ||
// | ||
async applyPatch(patchObject, graph, url) { | ||
@@ -77,14 +70,11 @@ return new Promise((resolve, reject) => graph.applyPatch(patchObject, graph.sym(url), err => { | ||
const message = err.message || err; // returns string at the moment | ||
return reject(new Error(`409 : The patch could not be applied. ${message}`)); // is this correct : not tested | ||
} | ||
resolve(graph); | ||
})); | ||
} // serialize graph to turtle | ||
} | ||
// serialize graph to turtle | ||
async writeGraph(graph, resource) { | ||
const resourceSym = graph.sym(resource.url); | ||
try { | ||
@@ -96,16 +86,13 @@ const serialized = $rdf.serialize(resourceSym, graph, resource.url, resource.contentType); | ||
} | ||
} // Creates a hash of the given text | ||
} | ||
// Creates a hash of the given text | ||
hash(text) { | ||
return crypto.createHash('md5').update(text).digest('hex'); | ||
} | ||
} // END OF CLASS RestPatch | ||
} // END OF CLASS RestPatch | ||
// PARSE SPARQL | ||
// | ||
async function parsePatchSparql(targetURI, patchURI, patchText) { | ||
const baseURI = patchURI.replace(/#.*/, ''); | ||
try { | ||
@@ -116,9 +103,8 @@ return $rdf.sparqlUpdateParser(patchText, $rdf.graph(), baseURI); | ||
} | ||
} // PARSE N3 | ||
} | ||
// PARSE N3 | ||
// | ||
async function parsePatchN3(targetURI, patchURI, patchText) { | ||
const patchGraph = $rdf.graph(); | ||
try { | ||
@@ -129,5 +115,3 @@ $rdf.parse(patchText, patchGraph, patchURI, 'text/n3'); | ||
} | ||
let firstResult; | ||
try { | ||
@@ -154,3 +138,2 @@ firstResult = await queryForFirstResult(patchGraph, `${PREFIXES} | ||
} | ||
const { | ||
@@ -161,7 +144,6 @@ '?insert': insert, | ||
} = firstResult; | ||
if (!insert && !deleted) { | ||
return [400, 'Patch should at least contain inserts or deletes.']; // throw error(400, 'Patch should at least contain inserts or deletes.') | ||
return [400, 'Patch should at least contain inserts or deletes.']; | ||
// throw error(400, 'Patch should at least contain inserts or deletes.') | ||
} | ||
return { | ||
@@ -172,6 +154,6 @@ insert, | ||
}; | ||
} // EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
} | ||
// EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
// | ||
function queryForFirstResult(store, sparql) { | ||
@@ -182,4 +164,5 @@ return new Promise((resolve, reject) => { | ||
return ['409 : No results.']; | ||
}); // TODO check status | ||
}); | ||
// TODO check status | ||
}); | ||
} |
@@ -6,3 +6,2 @@ // import { contentType as contentTypeLookup } from 'mime-types'; | ||
const linksExt = linkExt.concat('.meta.acl'); | ||
async function createServerlessPod(base) { | ||
@@ -22,6 +21,4 @@ console.log(`Creating pod at <${base}>`); | ||
} | ||
async function getContentType(path, type) { | ||
let ext = this.getExtension(path); | ||
if (!ext || ext === '.ttl' || ext === '.acl' || ext === '.meta' || type === "Container") { | ||
@@ -35,7 +32,6 @@ return 'text/turtle'; | ||
} | ||
function isAuxResource(o) { | ||
return linkExt.find(ext => this.getExtension(o) === ext); // return linkExt.find(ext => o.extension === ext); | ||
return linkExt.find(ext => this.getExtension(o) === ext); | ||
// return linkExt.find(ext => o.extension === ext); | ||
} | ||
async function getAuxResources(pathname) { | ||
@@ -48,14 +44,10 @@ if (pathname.endsWith('.acl')) return []; | ||
} | ||
async function generateRandomSlug(pathname, slug = uuidv1()) { | ||
let requestUrl = this.mungePath(pathname, slug); | ||
if (this.item.isContainer && !this.request.url.endsWith(this.pathSep)) requestUrl = requestUrl + this.pathSep; | ||
if (await this.perform('ITEM_EXISTS', requestUrl)) { | ||
slug = `${uuidv1()}-${slug}`; | ||
} | ||
return this.mungePath(pathname, slug); | ||
} | ||
export { createServerlessPod, getContentType, isAuxResource, getAuxResources, generateRandomSlug, linkExt, linksExt }; |
@@ -20,3 +20,2 @@ (function (global, factory) { | ||
_exports.getRequest = getRequest; | ||
function getRequest(uri, options) { | ||
@@ -28,3 +27,2 @@ const request = normalizeRequestKeys(options); | ||
request.body = request.body || ""; | ||
if (!validUrl(uri)) { | ||
@@ -38,3 +36,2 @@ request.url = null; | ||
} | ||
if (request.url && request.url.endsWith('.dummy')) { | ||
@@ -45,3 +42,2 @@ // rdflib does this !!! | ||
} | ||
return request; | ||
@@ -53,6 +49,4 @@ } | ||
function normalizeRequestKeys(opts) { | ||
let newOpts = {}; | ||
for (var o in opts) { | ||
@@ -63,6 +57,4 @@ if (o === 'host') { | ||
} | ||
return newOpts; | ||
} | ||
const validUrl = s => { | ||
@@ -80,3 +72,2 @@ try { | ||
function normalizeRequestMethod(method) { | ||
@@ -83,0 +74,0 @@ return method ? method.toUpperCase() : 'GET'; |
@@ -21,12 +21,9 @@ (function (global, factory) { | ||
_url = _interopRequireDefault(_url); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
//import libPath from "path"; | ||
//import libPath from "path"; | ||
var pathHandler; | ||
async function getItem(uri, request) { | ||
let url, pname; | ||
pathHandler = await this.perform('GET_PATH_HANDLER', uri); | ||
if (uri.startsWith('file')) { | ||
@@ -39,3 +36,2 @@ url = _url.default.format(request.url); | ||
} | ||
const item = await this.perform('GET_ITEM_INFO', pname, request); | ||
@@ -48,3 +44,2 @@ item.mode = item.mode ? item.mode : { | ||
item.pathname = pname; | ||
if (request.method === 'DELETE' && item.isContainer) { | ||
@@ -58,3 +53,2 @@ let files = await this.perform('GET_FILES', item.pathname); | ||
} | ||
this.getExtension = path => { | ||
@@ -65,6 +59,4 @@ path = path || this.item.pathname || ""; | ||
}; | ||
this.pathSep = pathHandler.sep; | ||
this.basename = pathHandler.extname; | ||
this.mungePath = (pathname, slug, options) => { | ||
@@ -75,3 +67,2 @@ pathname = pathHandler.join(pathname, slug); | ||
}; | ||
pname = request.method === "POST" ? this.mungePath(item.pathname, request.slug) : item.pathname; | ||
@@ -82,5 +73,6 @@ item.extension = this.getExtension(pname); | ||
item.isAcl = pname.match(/\.acl/); // TBD use LinkExt | ||
//item.isAuxResource = item.isAcl || this.extension === '.meta'; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
item.isAuxResource = pname.match(/\.(acl|meta)$/) ? true : false; | ||
/* | ||
@@ -130,3 +122,2 @@ let conflict | ||
*/ | ||
}); |
@@ -51,9 +51,6 @@ (function (global, factory) { | ||
}; | ||
async function handleRequest(uri, originalRequest) { | ||
const request = this.requestObj = await this.getRequest(uri, originalRequest); // | ||
const item = this.item = await this.getItem(uri, request); // | ||
// Errors we find in the request | ||
if (!request.url || !request.method) return 400; | ||
@@ -64,11 +61,9 @@ if (request.slug.endsWith('/')) return 400; | ||
if (request.method === 'PATCH' && !this.patch) return 405; | ||
if (request.method === 'POST' && !request.headers.link) return 400; // Errors we find by comparing the request & the itemRequested | ||
if (request.method === 'POST' && !request.headers.link) return 400; | ||
// Errors we find by comparing the request & the itemRequested | ||
if (item.isContainer && !item.contentType) item.contentType = "text/turtle"; | ||
if (item.folderFileConfusion) return 400; // can't have both /foo and /foo/ | ||
if (item.patchOnNonRdf) return 400; | ||
if (item.mode.write) item.mode.append = true; | ||
const method = methods[request.method]; | ||
if (item.isAuxResource) { | ||
@@ -78,3 +73,2 @@ if (item.isAcl) method.requiresControl = true; | ||
} | ||
if (!method) console.log(55, request.method); | ||
@@ -84,3 +78,2 @@ if (!method) return 409; | ||
if (method.requiresRead && !item.mode.read || method.requiresAppend && !item.mode.append || method.requiresWrite && !item.mode.write || method.requiresControl && !item.mode.control) return 401; | ||
if (method.requiresContentType && !request.headers['content-type']) { | ||
@@ -90,3 +83,2 @@ // console.log(request.method, "No Content Type"); | ||
} | ||
if (request.method === 'POST') { | ||
@@ -97,3 +89,2 @@ this.item.pathname = await this.generateRandomSlug(this.item.pathname, request.slug); | ||
if (request.method === 'PUT' || request.method === 'POST' || request.method === 'PATCH') { | ||
@@ -104,8 +95,5 @@ // if (item.isContainer) return 405; | ||
} | ||
let response = await this.perform(request.method); | ||
if (!response && request.method === 'DELETE' && item.isContainer) { | ||
let stillExists = await this.perform('ITEM_EXISTS', this.item.pathname); | ||
if (stillExists) { | ||
@@ -115,6 +103,4 @@ return 409; | ||
} | ||
return response; | ||
} // ENDS | ||
}); |
@@ -20,3 +20,2 @@ (function (global, factory) { | ||
_exports.handleResponse = handleResponse; | ||
/* | ||
@@ -28,2 +27,3 @@ url : file:///foo/bar.txt | ||
//import libPath from 'path'; | ||
const statusText = { | ||
@@ -43,6 +43,4 @@ 200: "OK", | ||
}; | ||
async function handleResponse(response, originalRequest) { | ||
let wrapHeaders = true; // {headers} instead of headers for Response | ||
let method = originalRequest.method || this.request.method || "GET"; | ||
@@ -60,3 +58,2 @@ let finalResponse = { | ||
*/ | ||
if (typeof response === 'number') { | ||
@@ -83,22 +80,23 @@ wrapHeaders = false; | ||
if (method.match(/(PUT)/) && finalResponse.headers.status == 200) { | ||
finalResponse.headers.status = 201; | ||
} | ||
if (method.match(/(DELETE|GET|HEAD)/) && finalResponse.headers.status == 201) { | ||
finalResponse.headers.status = 200; | ||
} | ||
let headers = {}; | ||
const request = this.requestObj; | ||
const item = this.item; | ||
const pathname = item.pathname; // const fn = libPath.basename(pathname); | ||
const pathname = item.pathname; | ||
// const fn = libPath.basename(pathname); | ||
const fn = pathname.replace(/.*\//, ''); | ||
headers['vary'] = 'accept,authorization,origin'; | ||
headers['access-control-expose-headers'] = 'accept-patch,accept-post,accept-put,allow,content-range,etag,last-modified,link,location,updates-via,wac-allow,www-authenticate'; | ||
headers['content-type'] = this.item.contentType; // CONTENT-TYPE | ||
headers.link = headers.link || createLinkHeader(item); // LINK | ||
const storageHeader = item.pathname === '/' ? ', <http://www.w3.org/ns/pim/space#Storage>; rel="type"' : ''; | ||
headers.link = headers.link || createLinkHeader(item) + storageHeader; // LINK | ||
headers.allow = createAllowHeader(this.patch, this.item.mode); // ALLOW | ||
headers.allow = createAllowHeader(item.pathname); // ALLOW | ||
@@ -111,6 +109,6 @@ headers['wac-allow'] = createWacHeader(this.item.mode); // WAC-ALLOW | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; // NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
if (this.response && this.response.headers) headers.location = this.response.headers.location; | ||
// NO, DON'T USE LOCATION headers.url = headers.location || pathname ; | ||
headers.url = pathname; | ||
if (method === "POST") { | ||
@@ -128,15 +126,14 @@ headers.url = this.request.url; | ||
} | ||
/* if (this.patch) { // ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} */ | ||
if (this.patch) { | ||
// ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
let body = finalResponse.body || this.response.body || ""; // Now we merge headers we created with response headers, prefering response | ||
Object.assign(headers, finalResponse.headers); //alert(finalResponse.headers.status) | ||
Object.assign(headers, finalResponse.headers); | ||
//alert(finalResponse.headers.status) | ||
headers.status = finalResponse.headers.status || this.response.headers.status || 500; | ||
let $rdf = typeof window != "undefined" && window.$rdf ? window.$rdf : typeof global != "undefined" && global.$rdf ? global.$rdf : null; | ||
/* | ||
@@ -167,12 +164,18 @@ async function serialize(uri,body,informat,outformat){ | ||
*/ | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers = createAcceptHeader(request, headers); // ACCEPT | ||
headers.statusText = headers.statusText || statusText[headers.status]; | ||
headers.etag = `W/"${(0, _uuid.v4)()}"`; | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; // Now we create & return the Response object | ||
headers['content-length'] = typeof Buffer != 'undefined' ? Buffer.byteLength(body, 'utf8') : typeof Blob != "undefined" ? new Blob([body]).size : 77; | ||
// TODO (?) last-modified | ||
// Now we create & return the Response object | ||
for (var h of Object.keys(headers)) { | ||
if (!headers[h]) delete headers[h]; | ||
} | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; | ||
if (!headers.url.match(/:/)) headers.url = (this.prefix || "file:") + "//" + headers.url; // headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// headers.location = headers.location || headers.url.replace(/^....?:\/\//,''); | ||
// if(!headers.location.match(/^file:/)) headers.location = "file://"+headers.location; | ||
@@ -182,3 +185,2 @@ | ||
body = ""; | ||
for (let k of Object.keys(headers)) { | ||
@@ -188,3 +190,2 @@ body = body + `${k}:${headers[k]}\n`; | ||
} | ||
if (originalRequest.plainResponse) { | ||
@@ -201,3 +202,2 @@ // from a server that wants to munge | ||
} | ||
wrapHeaders = true; | ||
@@ -212,3 +212,2 @@ headers = wrapHeaders ? { | ||
let responseObject; | ||
try { | ||
@@ -221,3 +220,2 @@ responseObject = new _crossFetch.Response(body, headers, { | ||
} | ||
return responseObject; | ||
@@ -227,3 +225,2 @@ } // end of handleResponse method | ||
function createWacHeader(mode) { | ||
@@ -235,7 +232,26 @@ if (!mode.read && !mode.write) return null; | ||
} | ||
function createAllowHeader(patch, mode) { | ||
return 'OPTIONS,HEAD' + (mode.read ? ',GET' : '') + (mode.write ? ',POST,PUT,DELETE' : '') + (mode.write && patch ? ',PATCH' : ''); | ||
function createAllowHeader(requestPath) { | ||
// root/ root/.acl can't be deleted | ||
let del = requestPath === '/' || requestPath === '/.acl' ? '' : ',DELETE'; | ||
// no PATCH on Container | ||
if (requestPath.endsWith('/')) return 'OPTIONS,HEAD,GET,POST,PUT' + del; | ||
// no POST on Document | ||
else return 'OPTIONS,HEAD,GET,PATCH,PUT' + del; | ||
} | ||
function createAcceptHeader(request, headers) { | ||
const status = headers.status; | ||
// no Accept header | ||
if (request.method.match(/DELETE/) || status >= 500 || status.toString().match(/401|403/)) return headers; | ||
// Accept headers on container | ||
if (request.url.endsWith('/')) { | ||
if (status === 404) headers['accept-put'] = ['*/*']; | ||
headers['accept-post'] = ['*/*']; | ||
} else { | ||
// Accept headers on document | ||
headers['accept-put'] = ['*/*']; | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
return headers; | ||
} | ||
function createLinkHeader(item) { | ||
@@ -246,14 +262,14 @@ let isContainer = item.isContainer; | ||
let ext = item.extension; | ||
if (ext === '.acl') // .acl not controlledBy or describedBy anything | ||
if (ext === '.acl') | ||
// .acl not controlledBy or describedBy anything | ||
return `<http://www.w3.org/ns/ldp#Resource>; rel="type"`;else if (ext === '.meta') { | ||
return `<${fn}.acl>; rel="acl",` // .meta controlledBy .meta.acl | ||
+ `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<${fn}.acl>; rel="acl"` // .meta controlledBy .meta.acl | ||
+ `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else if (isContainer) { | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Container>; rel="type",` + `<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Container>; rel="type"` + `, <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} else { | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return link; | ||
} | ||
} // THE END! | ||
}); |
@@ -23,9 +23,6 @@ (function (global, factory) { | ||
_restPatch = _interopRequireDefault(_restPatch); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
class SolidRest { | ||
constructor(options) { | ||
options = options || {}; | ||
if (!options.plugin) { | ||
@@ -35,3 +32,2 @@ console.log(`You must specify a plugin storage handler!`); | ||
} | ||
this.storage = options.plugin; | ||
@@ -54,3 +50,2 @@ this.handleRequest = _handleRequest.handleRequest.bind(this); | ||
} | ||
async fetch(uri, options = {}) { | ||
@@ -60,3 +55,2 @@ let response = await this.handleRequest(uri, options); | ||
} | ||
async login(options) { | ||
@@ -70,21 +64,15 @@ options = { | ||
} | ||
async itemExists(pathname) { | ||
return await this.perform('ITEM_EXISTS', pathname); | ||
} | ||
isPatchConflictError(response) { | ||
if (response === 400) return true; | ||
} | ||
isAccessError(response) { | ||
if (response === 401) return true; | ||
} | ||
/* =========================================================== */ | ||
/* REST METHODS */ | ||
/* =========================================================== */ | ||
async GET(url) { | ||
@@ -95,3 +83,2 @@ return await this.fetch(url, { | ||
} | ||
async HEAD(url) { | ||
@@ -102,3 +89,2 @@ return await this.fetch(url, { | ||
} | ||
async EXISTS(url) { | ||
@@ -114,3 +100,2 @@ try { | ||
} | ||
async PUT(url, text, ctype) { | ||
@@ -126,3 +111,2 @@ ctype = ctype || 'text/turtle'; | ||
} | ||
async PATCH(url, patchContent, patchContentType) { | ||
@@ -140,3 +124,2 @@ patchContentType = patchContent || "text/n3"; | ||
} | ||
async DELETE(url) { | ||
@@ -147,3 +130,2 @@ return await this.fetch(url, { | ||
} | ||
async POST(parent, item, content, link) { | ||
@@ -160,3 +142,2 @@ return await this.fetch(parent, { | ||
} | ||
async postFile(parent, file, content) { | ||
@@ -166,3 +147,2 @@ let link = '<http://www.w3.org/ns/ldp#Resource>; rel="type"'; | ||
} | ||
async postFolder(parent, folder) { | ||
@@ -172,7 +152,4 @@ let link = '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"'; | ||
} | ||
} // THE END | ||
_exports.default = SolidRest; | ||
}); |
@@ -20,3 +20,2 @@ (function (global, factory) { | ||
_exports.default = perform; | ||
async function perform(method, pathname, content, ctype) { | ||
@@ -33,3 +32,2 @@ this.request = this.requestObj; | ||
}; | ||
switch (method) { | ||
@@ -39,3 +37,2 @@ case 'STORAGE_NAME': | ||
break; | ||
case 'ITEM_EXISTS': | ||
@@ -45,7 +42,5 @@ pathname = pathname.replace('file://', ''); | ||
break; | ||
case 'LOGIN': | ||
return await this.storage.login(this.request.loginoptions); | ||
break; | ||
case 'ITEM_TYPE': | ||
@@ -55,20 +50,15 @@ // Container/Resource | ||
break; | ||
case 'GET_CONTENT_TYPE': | ||
return await this.storage.getContentType(pathname); // return await this.storage.getContentType(pathname).bind(this.storage); | ||
return await this.storage.getContentType(pathname); | ||
// return await this.storage.getContentType(pathname).bind(this.storage); | ||
break; | ||
case 'GET_PATH_HANDLER': | ||
return await this.storage.getPathHandler(pathname); | ||
break; | ||
case 'GET_ITEM_INFO': | ||
return await this.storage.getItemInfo(pathname, this.request); | ||
break; | ||
case 'GET_FILES': | ||
return await this.storage.getContainer(pathname); | ||
break; | ||
case 'DELETE': | ||
@@ -82,8 +72,5 @@ if (this.item.isContainer) { | ||
} | ||
break; | ||
case 'DELETE_AUX_RESOURCES': | ||
const links = (await this.getAuxResources(pathname)) || []; | ||
try { | ||
@@ -98,18 +85,13 @@ links.map(async link => { | ||
} | ||
return 200; | ||
break; | ||
case 'CREATE_INTERMEDIATE_CONTAINERS': | ||
return (await this.storage.makeContainers(pathname)) || 1; | ||
break; | ||
case 'GET': | ||
if (this.item.isContainer) { | ||
let files = await this.storage.getContainer(pathname); | ||
if (files.headers) { | ||
return files; | ||
} | ||
return await this.containerAsTurtle(pathname, files, this.request.typewanted, this); | ||
@@ -119,7 +101,5 @@ } else { | ||
if (!thing) return false; | ||
if (thing.headers) { | ||
return thing; | ||
} | ||
this.response.body = thing; | ||
@@ -129,5 +109,3 @@ this.response.headers.status = 200; | ||
} | ||
break; | ||
case 'OPTIONS': | ||
@@ -137,7 +115,5 @@ case 'HEAD': | ||
break; | ||
case 'PUT': | ||
content = content || this.request.body; | ||
ctype = ctype || this.item.contentType || ""; // console.log('content for put',content); | ||
let x = await this.storage.putResource(pathname, content, ctype); // console.log('response from put',x); | ||
@@ -148,3 +124,2 @@ | ||
break; | ||
case 'FULL_PUT': | ||
@@ -157,3 +132,2 @@ let success = await this.storage.makeContainers(pathname); | ||
break; | ||
case 'POST': | ||
@@ -169,5 +143,3 @@ if (this.request.headers.link.match("Container")) { | ||
} | ||
break; | ||
case 'PATCH': | ||
@@ -185,13 +157,11 @@ const contentType = this.item.contentType; | ||
if (!exists) await this.perform('FULL_PUT', pathname, "", ctype); | ||
; // 415 patchOnNonTurtle is handled already in handleRequest.js | ||
; | ||
// 415 patchOnNonTurtle is handled already in handleRequest.js | ||
let oldContent = await this.storage.getResource(pathname); | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; // if (!oldContent) return false; | ||
oldContent = oldContent && oldContent.body ? oldContent.body : oldContent; | ||
// if (!oldContent) return false; | ||
oldContent = typeof oldContent === 'string' ? oldContent : oldContent.toString(); | ||
let newContent, patchStatus; | ||
try { | ||
[patchStatus, newContent] = await this.patch.patchContent(oldContent, contentType, this.request); | ||
if (patchStatus !== 200) { | ||
@@ -209,7 +179,7 @@ return { | ||
}; | ||
} // const status = await this.storage.makeContainers(pathname); | ||
} | ||
// const status = await this.storage.makeContainers(pathname); | ||
// if (!status) return false; | ||
// let putStatus = await this.storage.putResource(pathname, this.request.bod); | ||
let putStatus = await this.storage.putResource(pathname, newContent); | ||
@@ -221,3 +191,2 @@ putStatus = putStatus && putStatus.body ? putStatus.body : putStatus; | ||
} // ENDS | ||
}); |
@@ -20,11 +20,9 @@ (function (global, factory) { | ||
_exports.default = containerAsTurtle; | ||
// import libPath from 'path'; | ||
// import libPath from 'path'; | ||
async function containerAsTurtle(pathname, contentsArray, typeWanted, self) { | ||
const pathSep = self.pathSep; | ||
function basename(path) { | ||
return path.substr(path.lastIndexOf(self.pathSep) + 1); | ||
} | ||
let filenames = contentsArray.filter(item => { | ||
@@ -43,7 +41,6 @@ if (item.path && !item.path.endsWith('.acl') && !item.path.endsWith('.meta')) { | ||
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. | ||
<> a ldp:BasicContainer, ldp:Container | ||
`; | ||
<> a ldp:BasicContainer, ldp:Container`; | ||
if (filenames.length) { | ||
str = str + "; ldp:contains\n"; | ||
str = str + ";\n ldp:contains\n"; // alain | ||
@@ -55,3 +52,2 @@ for (var i = 0; i < filenames.length; i++) { | ||
fn = basename(fn); // contained resources are relative to folder | ||
if (filenames[i].isContainer && !fn.endsWith("/")) fn = fn + "/"; | ||
@@ -61,3 +57,2 @@ str = str + ` <${fn}>,\n`; | ||
let ctype, size, mtime, modified; | ||
if (self && self.storage.getMetadata) { | ||
@@ -73,19 +68,21 @@ try { | ||
} | ||
} else if (filenames[i].metadata) { | ||
size = filenames[i].metadata.size; | ||
mtime = filenames[i].metadata.mtimeMs; | ||
modified = new Date(mtime).toISOString(); | ||
} | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; // REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype || (await self.getContentType(fn, ftype)) || ""; | ||
// REMOVE CHARSET FROM CONTENT-TYPE | ||
ctype = ctype.replace(/;.*/, ''); | ||
ftype = filenames[i].isContainer ? "ldp:Container; a ldp:BasicContainer; a ldp:Resource" : "ldp:Resource"; | ||
str2 = str2 + `<${fn}> a ${ftype}.\n`; | ||
if (ctype) str2 = str2 + `<${fn}> a <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>.\n`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
str2 = str2 + `<${fn}> a ${ftype}`; | ||
if (ctype && !filenames[i].isContainer) | ||
// no media-type for Container | ||
str2 = str2 + `, <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
if (size) { | ||
str2 = str2 + `<${fn}> stat:size ${size}; stat:mtime ${mtime}; dct:"${modified}"^^xsd:dateTime.\n`; | ||
str2 = str2 + `;\n stat:size ${size};\n stat:mtime ${mtime};\n dct:modified "${modified}"^^xsd:dateTime.\n`; | ||
} | ||
} | ||
str = str.replace(/,\n$/, ""); | ||
} | ||
str = str + `.\n` + str2; // str = _makeStream(str); | ||
@@ -92,0 +89,0 @@ |
@@ -20,3 +20,3 @@ (function (global, factory) { | ||
_exports.public_content = _exports.profile_content = _exports.private_content = _exports.prefs_content = _exports.acl_content = void 0; | ||
const profile_content = `@prefix : <#>. | ||
const profile_content = _exports.profile_content = `@prefix : <#>. | ||
@prefix jef: <../>. | ||
@@ -54,4 +54,3 @@ @prefix ldp: <http://www.w3.org/ns/ldp#>. | ||
`; | ||
_exports.profile_content = profile_content; | ||
const prefs_content = `@prefix : <#>. | ||
const prefs_content = _exports.prefs_content = `@prefix : <#>. | ||
@prefix solid: <http://www.w3.org/ns/solid/terms#>. | ||
@@ -70,4 +69,3 @@ @prefix sp: <http://www.w3.org/ns/pim/space#>. | ||
`; | ||
_exports.prefs_content = prefs_content; | ||
const public_content = `@prefix : <#>. | ||
const public_content = _exports.public_content = `@prefix : <#>. | ||
@prefix solid: <https://www.w3.org/ns/solid/terms#>. | ||
@@ -85,4 +83,3 @@ @prefix terms: <http://purl.org/dc/terms/>. | ||
`; | ||
_exports.public_content = public_content; | ||
const private_content = ` | ||
const private_content = _exports.private_content = ` | ||
@prefix solid: <https://www.w3.org/ns/solid/terms#>. | ||
@@ -93,4 +90,3 @@ <> | ||
`; | ||
_exports.private_content = private_content; | ||
const acl_content = `@prefix acl: <http://www.w3.org/ns/auth/acl#>. | ||
const acl_content = _exports.acl_content = `@prefix acl: <http://www.w3.org/ns/auth/acl#>. | ||
@prefix foaf: <http://xmlns.com/foaf/0.1/>. | ||
@@ -120,4 +116,2 @@ | ||
/* ENDS */ | ||
_exports.acl_content = acl_content; | ||
}); |
@@ -28,3 +28,2 @@ (function (global, factory) { | ||
}; | ||
class RestPatch { | ||
@@ -34,3 +33,2 @@ constructor(passedRDF) { | ||
} | ||
async patchContent(content, contentType, request) { | ||
@@ -47,10 +45,7 @@ const url = request.url; | ||
const parsePatch = PATCH_PARSERS[patch.contentType]; | ||
if (!parsePatch) { | ||
return [415, `415 Unsupported patch content type: ${patch.contentType}`]; | ||
} // Parse the patch document and verify permissions | ||
} | ||
// Parse the patch document and verify permissions | ||
const patchUri = `${url}#patch`; | ||
try { | ||
@@ -63,3 +58,2 @@ const patchObject = await parsePatch(url, patchUri, patch.text); | ||
*/ | ||
let insertStmts = patch.text.match(/INSERT/g); | ||
@@ -73,10 +67,9 @@ if (insertStmts && insertStmts.length > 1) return [400, "can not have multiple INSERT statements in a patch"]; | ||
} | ||
} // PARSE ORIGINAL DOCUMENT | ||
} | ||
// PARSE ORIGINAL DOCUMENT | ||
// | ||
async readGraph(fileContents, resource) { | ||
const graph = $rdf.graph(); | ||
if (!fileContents.length) return graph; | ||
try { | ||
@@ -87,8 +80,7 @@ $rdf.parse(fileContents, graph, resource.url, resource.contentType); | ||
} | ||
return graph; | ||
} | ||
return graph; | ||
} // APPLY PATCH | ||
// APPLY PATCH | ||
// | ||
async applyPatch(patchObject, graph, url) { | ||
@@ -98,14 +90,11 @@ return new Promise((resolve, reject) => graph.applyPatch(patchObject, graph.sym(url), err => { | ||
const message = err.message || err; // returns string at the moment | ||
return reject(new Error(`409 : The patch could not be applied. ${message}`)); // is this correct : not tested | ||
} | ||
resolve(graph); | ||
})); | ||
} // serialize graph to turtle | ||
} | ||
// serialize graph to turtle | ||
async writeGraph(graph, resource) { | ||
const resourceSym = graph.sym(resource.url); | ||
try { | ||
@@ -117,19 +106,14 @@ const serialized = $rdf.serialize(resourceSym, graph, resource.url, resource.contentType); | ||
} | ||
} // Creates a hash of the given text | ||
} | ||
// Creates a hash of the given text | ||
hash(text) { | ||
return crypto.createHash('md5').update(text).digest('hex'); | ||
} | ||
} // END OF CLASS RestPatch | ||
} // END OF CLASS RestPatch | ||
// PARSE SPARQL | ||
// | ||
_exports.default = RestPatch; | ||
async function parsePatchSparql(targetURI, patchURI, patchText) { | ||
const baseURI = patchURI.replace(/#.*/, ''); | ||
try { | ||
@@ -140,9 +124,8 @@ return $rdf.sparqlUpdateParser(patchText, $rdf.graph(), baseURI); | ||
} | ||
} // PARSE N3 | ||
} | ||
// PARSE N3 | ||
// | ||
async function parsePatchN3(targetURI, patchURI, patchText) { | ||
const patchGraph = $rdf.graph(); | ||
try { | ||
@@ -153,5 +136,3 @@ $rdf.parse(patchText, patchGraph, patchURI, 'text/n3'); | ||
} | ||
let firstResult; | ||
try { | ||
@@ -178,3 +159,2 @@ firstResult = await queryForFirstResult(patchGraph, `${PREFIXES} | ||
} | ||
const { | ||
@@ -185,7 +165,6 @@ '?insert': insert, | ||
} = firstResult; | ||
if (!insert && !deleted) { | ||
return [400, 'Patch should at least contain inserts or deletes.']; // throw error(400, 'Patch should at least contain inserts or deletes.') | ||
return [400, 'Patch should at least contain inserts or deletes.']; | ||
// throw error(400, 'Patch should at least contain inserts or deletes.') | ||
} | ||
return { | ||
@@ -196,6 +175,6 @@ insert, | ||
}; | ||
} // EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
} | ||
// EXECUTE FIRST SPARQL QUERY IN STORE & RETURN RESULTS | ||
// | ||
function queryForFirstResult(store, sparql) { | ||
@@ -206,5 +185,6 @@ return new Promise((resolve, reject) => { | ||
return ['409 : No results.']; | ||
}); // TODO check status | ||
}); | ||
// TODO check status | ||
}); | ||
} | ||
}); |
@@ -26,13 +26,8 @@ (function (global, factory) { | ||
pod = _interopRequireWildcard(pod); | ||
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } | ||
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } | ||
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } | ||
// import { contentType as contentTypeLookup } from 'mime-types'; | ||
const linkExt = ['.acl', '.meta']; | ||
_exports.linkExt = linkExt; | ||
const linksExt = linkExt.concat('.meta.acl'); | ||
_exports.linksExt = linksExt; | ||
const linkExt = _exports.linkExt = ['.acl', '.meta']; | ||
const linksExt = _exports.linksExt = linkExt.concat('.meta.acl'); | ||
async function createServerlessPod(base) { | ||
@@ -52,6 +47,4 @@ console.log(`Creating pod at <${base}>`); | ||
} | ||
async function getContentType(path, type) { | ||
let ext = this.getExtension(path); | ||
if (!ext || ext === '.ttl' || ext === '.acl' || ext === '.meta' || type === "Container") { | ||
@@ -65,7 +58,6 @@ return 'text/turtle'; | ||
} | ||
function isAuxResource(o) { | ||
return linkExt.find(ext => this.getExtension(o) === ext); // return linkExt.find(ext => o.extension === ext); | ||
return linkExt.find(ext => this.getExtension(o) === ext); | ||
// return linkExt.find(ext => o.extension === ext); | ||
} | ||
async function getAuxResources(pathname) { | ||
@@ -78,13 +70,10 @@ if (pathname.endsWith('.acl')) return []; | ||
} | ||
async function generateRandomSlug(pathname, slug = (0, _uuid.v1)()) { | ||
let requestUrl = this.mungePath(pathname, slug); | ||
if (this.item.isContainer && !this.request.url.endsWith(this.pathSep)) requestUrl = requestUrl + this.pathSep; | ||
if (await this.perform('ITEM_EXISTS', requestUrl)) { | ||
slug = `${(0, _uuid.v1)()}-${slug}`; | ||
} | ||
return this.mungePath(pathname, slug); | ||
} | ||
}); |
{ | ||
"name": "@solid-rest/core", | ||
"version": "2.1.18", | ||
"version": "2.1.19", | ||
"author": "Jeff Zucker", | ||
"contributors": [ | ||
"Alain Bourgeois", | ||
"Rahul Gupta" | ||
], | ||
"license": "MIT", | ||
@@ -32,10 +36,10 @@ "description": "treat any storage as a mini Solid server", | ||
"dependencies": { | ||
"cross-fetch": "^3.1.5", | ||
"uuid": "8.3.1" | ||
"cross-fetch": "^4.0.0", | ||
"uuid": "9.0.1" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.12.10", | ||
"@babel/core": "^7.14.6", | ||
"@babel/plugin-transform-modules-commonjs": "^7.12.1", | ||
"@babel/plugin-transform-modules-umd": "^7.16.0", | ||
"@babel/cli": "^7.23.9", | ||
"@babel/core": "^7.23.9", | ||
"@babel/plugin-transform-modules-commonjs": "^7.23.3", | ||
"@babel/plugin-transform-modules-umd": "^7.23.3", | ||
"babel-preset-es2015": "6.24.1", | ||
@@ -42,0 +46,0 @@ "babel-preset-stage-0": "6.24.1" |
@@ -59,3 +59,3 @@ /* | ||
if(method.match(/(PUT)/) && finalResponse.headers.status == 200){ | ||
finalResponse.headers.status = 201 | ||
finalResponse.headers.status = 201 | ||
} | ||
@@ -73,9 +73,14 @@ if(method.match(/(DELETE|GET|HEAD)/) && finalResponse.headers.status == 201){ | ||
// const fn = libPath.basename(pathname); | ||
const fn = pathname.replace(/.*\//,''); | ||
const fn = pathname.replace(/.*\//,''); | ||
headers['vary'] = 'accept,authorization,origin' | ||
headers['access-control-expose-headers'] = 'accept-patch,accept-post,accept-put,allow,content-range,etag,last-modified,link,location,updates-via,wac-allow,www-authenticate' | ||
headers['content-type'] = this.item.contentType; // CONTENT-TYPE | ||
headers.link = headers.link || createLinkHeader(item); // LINK | ||
const storageHeader = item.pathname === '/' ? ', <http://www.w3.org/ns/pim/space#Storage>; rel="type"' : '' | ||
headers.link = headers.link || (createLinkHeader(item) + storageHeader); // LINK | ||
headers.allow = createAllowHeader(this.patch, this.item.mode); // ALLOW | ||
headers.allow = createAllowHeader(item.pathname) // ALLOW | ||
@@ -104,6 +109,6 @@ headers['wac-allow'] = createWacHeader(this.item.mode); // WAC-ALLOW | ||
} | ||
if (this.patch) { // ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['application/sparql-update']; | ||
/* if (this.patch) { // ACCEPT-PATCH & MS-AUTHOR-VIA | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
} */ | ||
@@ -146,5 +151,9 @@ | ||
headers = createAcceptHeader(request, headers) // ACCEPT | ||
headers.etag = `W/"${uuid()}"`; | ||
headers['content-length'] = (typeof Buffer !='undefined') ?Buffer.byteLength(body,'utf8') :(typeof Blob!="undefined") ?(new Blob([body])).size :77; | ||
// TODO (?) last-modified | ||
// Now we create & return the Response object | ||
@@ -209,6 +218,28 @@ for(var h of Object.keys(headers)){ | ||
function createAllowHeader(patch, mode) { | ||
return 'OPTIONS,HEAD' + (mode.read ? ',GET' : '') + (mode.write ? ',POST,PUT,DELETE' : '') + (mode.write && patch ? ',PATCH' : ''); | ||
function createAllowHeader(requestPath) { | ||
// root/ root/.acl can't be deleted | ||
let del = (requestPath === '/' || requestPath === '/.acl') ? '' : ',DELETE' | ||
// no PATCH on Container | ||
if (requestPath.endsWith('/')) return 'OPTIONS,HEAD,GET,POST,PUT' + del | ||
// no POST on Document | ||
else return 'OPTIONS,HEAD,GET,PATCH,PUT' + del | ||
} | ||
function createAcceptHeader(request, headers) { | ||
const status = headers.status | ||
// no Accept header | ||
if (request.method.match(/DELETE/) || status >= 500 || status.toString().match(/401|403/)) return headers | ||
// Accept headers on container | ||
if (request.url.endsWith('/')) { | ||
if (status === 404) headers['accept-put'] = ['*/*']; | ||
headers['accept-post'] = ['*/*']; | ||
} else { | ||
// Accept headers on document | ||
headers['accept-put'] = ['*/*']; | ||
headers['accept-patch'] = ['text/n3', 'application/sparql-update']; | ||
headers['ms-author-via'] = ["SPARQL"]; | ||
} | ||
return headers | ||
} | ||
function createLinkHeader(item) { | ||
@@ -222,12 +253,12 @@ let isContainer = item.isContainer; | ||
else if (ext === '.meta') { | ||
return `<${fn}.acl>; rel="acl",` // .meta controlledBy .meta.acl | ||
+ `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<${fn}.acl>; rel="acl"` // .meta controlledBy .meta.acl | ||
+ `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} | ||
else if (isContainer) { | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Container>; rel="type",` + `<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return `<.meta>; rel="describedBy", <.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Container>; rel="type"` + `, <http://www.w3.org/ns/ldp#BasicContainer>; rel="type"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
} | ||
else { | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl",` + `<http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
let link = `<${fn}.meta>; rel="describedBy", <${fn}.acl>; rel="acl"` + `, <http://www.w3.org/ns/ldp#Resource>; rel="type"`; | ||
return link; | ||
} | ||
} // THE END! |
@@ -22,7 +22,7 @@ // import libPath from 'path'; | ||
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>. | ||
<> a ldp:BasicContainer, ldp:Container | ||
`; | ||
<> a ldp:BasicContainer, ldp:Container`; | ||
if (filenames.length) { | ||
str = str + "; ldp:contains\n"; | ||
str = str + ";\n ldp:contains\n"; // alain | ||
@@ -47,2 +47,6 @@ for (var i = 0; i < filenames.length; i++) { | ||
catch(e){console.log(e)} | ||
} else if (filenames[i].metadata) { | ||
size = filenames[i].metadata.size | ||
mtime = filenames[i].metadata.mtimeMs | ||
modified = new Date(mtime).toISOString() | ||
} | ||
@@ -53,7 +57,7 @@ ctype = ctype || await self.getContentType(fn, ftype) || ""; | ||
ftype = filenames[i].isContainer ? "ldp:Container; a ldp:BasicContainer; a ldp:Resource" : "ldp:Resource"; | ||
str2 = str2 + `<${fn}> a ${ftype}.\n`; | ||
if(ctype) | ||
str2 = str2 + `<${fn}> a <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>.\n`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
str2 = str2 + `<${fn}> a ${ftype}`; | ||
if(ctype && !filenames[i].isContainer) // no media-type for Container | ||
str2 = str2 + `, <http://www.w3.org/ns/iana/media-types/${ctype}#Resource>`; // str2 = str2 + `<${fn}> :type "${ctype}".\n` | ||
if(size){ | ||
str2 = str2 + `<${fn}> stat:size ${size}; stat:mtime ${mtime}; dct:"${modified}"^^xsd:dateTime.\n` | ||
str2 = str2 + `;\n stat:size ${size};\n stat:mtime ${mtime};\n dct:modified "${modified}"^^xsd:dateTime.\n` | ||
} | ||
@@ -60,0 +64,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
172252
4408
+ Addedcross-fetch@4.0.0(transitive)
+ Addeduuid@9.0.1(transitive)
- Removedcross-fetch@3.1.8(transitive)
- Removeduuid@8.3.1(transitive)
Updatedcross-fetch@^4.0.0
Updateduuid@9.0.1