Closed michielbdejong closed 3 years ago
I'd prefer not to steer users to direct file reads with fs. Here's an example about the same length as yours that uses solid-logic and shows the power of isomorphically treating the file system as a pod. It's multi-directional, preserves content-type (so e.g. foo.jsonld would get the right content type), and has possibility of easily including ACLs and binaries.
/** Copies files from any folder to any other folder, overwriting destination
* it is multi-way: pod-to-local, local-to-pod, pod-to-pod, local-to-local
*
* USAGE : copyOverwrite <from_folder> <to_folder>
*
* local URLs should start with ./ and be relative to current working dir
* pod URLs should be full https URLs
*/
import { SolidNodeClient } from 'solid-node-client';
import { SolidLogic } from 'solid-logic';
import * as $rdf from 'rdflib';
const client = new SolidNodeClient();
const logic = new SolidLogic({ fetch:client.fetch.bind(client) });
async function cp(from,to) {
from = munge(from);
to = munge(to);
if( to.startsWith('https') || from.startsWith('https')) await client.login();
await logic.load(from);
const promises = logic.getContainerElements($rdf.sym(from)).map(
async (fileNode) => {
if(fileNode.uri.endsWith('/')) return // don't copy subdirs, TBD:recurse
console.log(`reading : ${fileNode.uri}`)
const res1 = await client.fetch(fileNode.uri);
let ctype = res1.headers.get('content-type'); // use correct content-type
let content = await res1.text(); // TBD: handle binary files
const uri = to + fileNode.uri.replace( from, '');
console.log(`writing : ${uri} as ${ctype}`)
const res2 = await client.fetch( uri, {
headers: {'Content-Type': ctype},
method: 'PUT',
body: content
});
console.log( uri, res2.status );
// TBD : if wac-allow user=Control, look for and copy ACL if it exists
}
);
await Promise.all(promises);
}
function munge(str){
str = str.replace(/^\.\//,'file://' + process.cwd() + '/');
return str.endsWith('/') ? str : str + '/';
}
cp( process.argv[2], process.argv[3] );
Since solid-node-client supports multiple identies, it would also be possible to write this script with two logins so that a webId on podA could copy to podB as a different webId.
Also, I do this all the time myself, but your content-type is in the wrong place. The content-type is not at the top level, it needs to be in a property of headers. I think you'll find that all the files you copied with your script end up as text/plain on NSS.
Also note that the only reason I need to import rdflib into this script is to send a namedNode to logic.getContainerElements().
I plan to write more documentation about how to use solid-node-client with other libraries (solid-logic, solid-client, rdflib, solid-file-client, ...). So I guess I am thinking about holding off on examples till that documentation is ready.
Thanks! I'll close this one then.
Attempts to fix #8.