nodeSolidServer / solid-auth-client

A browser library for performing authenticated requests to Solid pods
https://solid.github.io/solid-auth-client/
MIT License
95 stars 42 forks source link

Support an in-browser POD : local storage via data:// scheme #113

Open jeff-zucker opened 5 years ago

jeff-zucker commented 5 years ago

This may be hair-brained, but it could potentially have many uses. It could work by making a cut-out in solid-auth-client.fetch() that handed fetching of data:// URIs to a local-storage aware library that returns success/failure in an object similar to what an HTTP fetch returns. There could be sync apps that would use standard rdflib or ldflex methods to copy files to a cloud-based POD. I can work on this if you think it's useful.

michielbdejong commented 5 years ago

Or how about a browser extension that stores data in its own storage? Would love to brainstorm about this!

linonetwo commented 5 years ago

How about a separate library that can create a POD on the service worker? Likes https://github.com/linonetwo/ipfs-browser-gateway

But SW is not very convenient for some of the developers and environments. So yes, if it's integrated into solid-auth-client it can be easier to use it.

I think a potential usage is using it as a local cache when the user doesn't actually have a WebID. If you are new to SoLiD and want to try out a note-taking app, It may provide a local POD for you. (maybe

jeff-zucker commented 5 years ago

I think a browser extension is a great idea to use in addition to my idea rather than a replacement for it. The advantage of building it into solid-auth-client is that any app will then be able to dependably use rdflib/query-ldflex to interact with the local storage (or indexed db) whereas they could not count on having an extension installed.

jeff-zucker commented 5 years ago

@michielbdejong I've created a file:// handler for rdflib which basically treats the file system as a minimal Solid REST server. It might be a useful piece of a browser extension for an in-browser POD. It also has some tests that might be useful elsewhere.

jeff-zucker commented 5 years ago

My in-browser-pod is almost ready for prime time. It can store and access resources and containers in localStorage via rdflib. It would be accessible in all apps if you include a cutout for it in solid-auth-client (if the IRI scheme is app://, use solid-rest-browser's fetch). Here's links to a working demo and the code repo.. It's not finalized, but it does the basics, such as returning a GET request for a Container as a set of LDP:contains triples.

jeff-zucker commented 5 years ago

Update : the in-browser storage can now handle GET, PUT, POST, DELETE on resources and containers according to (my interpretation of) the Solid REST spec. It can transparently handle all rdflib methods except those requiring PATCH and that most likely goes for most other Solid libraries. It doesn't touch ACL or other related specs, only the REST interaction. I've had reports it works fine on iPhone and Android.

jeff-zucker commented 5 years ago

@RubenVerborgh I am ready to submit a PR to include a single line at the top of solid-auth-client's fetch

if(input.startsWith("app")) return appfetch(input,options);

Should I expect the user to load solid-rest-browser themselves so that appfetch pre-exists? Or should it be imported by solid-auth-client? Or are you considering not including the PR at all. If so, please explain.

RubenVerborgh commented 5 years ago

If possible, I would suggest require('solid-rest-browser') and then configure webpack such that it defaults to window.something.something (https://github.com/linkeddata/rdflib.js/blob/v0.20.1/webpack.config.js#L45-L46). That gives people the option of distributing/packaging it the way they want.

jeff-zucker commented 5 years ago

I'm sorry, I'm pretty slow-witted when it comes to require/import and webpack. Could you clarify where the require would occur and what you mean about the webpack?

RubenVerborgh commented 5 years ago

Sure, so that would need to become:

if(input.startsWith("app:"))
  return require("solid-rest-browser").fetch(input,options);

and https://github.com/solid/solid-auth-client/blob/v2.3.0/webpack/webpack.common.config.js#L28 would need something like

'externals": {
    'solid-rest-browser': {
        root: ['whatever', 'whatever'],
        commonjs: 'solid-rest-browser',
        commonjs2: 'solid-rest-browser',
    },
}
jeff-zucker commented 5 years ago

Ah! Thanks so much! I am starting to get it. It does sound like the cleanest way. Two more questions: users will need to import solid-rest-browser in a script tag placed before the script tag for solid-auth-client? And solid-rest-browser will not be included at all in the package.json for solid-auth-client? Oops third question: users will get an error if they try an app:// url without having imported it ... should there perhaps be a try/catch around the require in solid-auth-client to warn them?

RubenVerborgh commented 5 years ago

Two more questions: users will need to import solid-rest-browser in a script tag placed before the script tag for solid-auth-client?

If they use the default webpack build solid-auth-client.bundle.js, yes. If they require the client in their own apps, then no.

And solid-rest-browser will not be included at all in the package.json for solid-auth-client?

It would actually. It would just not be bundled with the default webpack build.

users will get an error if they try an app:// url without having imported it ... should there perhaps be a try/catch around the require in solid-auth-client to warn them?

That wouldn't be really clean, because a require is not expected to fail. Instead, we might want to configure webpack to include a stub. Now, we're telling webpack "look in window.something.something", whereas we could say "include this try/catch stub" (and that stub might very well be part of a separate file in solid-rest-browser).

jeff-zucker commented 5 years ago

Great! I'll set that all up and submit a PR. Thanks very much for your help!