Components.js icon indicating copy to clipboard operation
Components.js copied to clipboard

Custom components.js serialization

Open jeswr opened this issue 3 years ago • 9 comments

Issue type:

  • :heavy_plus_sign: Feature request

Description:

Building on this comment I thought I should share my thoughts on a javascriptish serialization for components.js files. It should be fairly quick to throw together an MVP for this in a day or so (using https://github.com/dsherret/ts-morph to parse the file and then traversing the AST to generate quads) which I'm happy to do in my own time in a couple of weeks.

To give this by example consider the following CSS config. My proposal is that this would roughly become

default.components.ts

// @context https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^4.0.0/components/context.jsonld

import * from "files-scs:config/ldp/handler/components/authorizer.json";
import * from "files-scs:config/ldp/handler/components/error-handler.json";
import * from "files-scs:config/ldp/handler/components/operation-handler.json";
import * from "files-scs:config/ldp/handler/components/operation-metadata.json";
import * from "files-scs:config/ldp/handler/components/request-parser.json";
import * from "files-scs:config/ldp/handler/components/response-writer.json";

const serverLink = text => link(`urn:solid-server:default:${text}`)

export {
  /**
  * The main entry point into the main Solid behaviour.
  */
  "urn:solid-server:default:LdpHandler": new ParsingHttpHandler({args: {
    requestParser: serverLink("RequestParser"),
    metadataCollector: serverLink("OperationMetadataCollector"),
    errorHandler: serverLink("ErrorHandler"),
    responseWriter: serverLink("ResponseWriter"),
    operationHandler: new AuthorizingHttpHandler({
      credentialsExtractor: serverLink("CredentialsExtractor"),
        modesExtractor: serverLink("ModesExtractor"),
        permissionReader: serverLink("PermissionReader"),
        authorizer: serverLink("Authorizer"),
        perationHandler: serverLink("OperationHandler")
    }})
}

or equivalently

// @context https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^4.0.0/components/context.jsonld

import * from "files-scs:config/ldp/handler/components/authorizer.json";
import * from "files-scs:config/ldp/handler/components/error-handler.json";
import * from "files-scs:config/ldp/handler/components/operation-handler.json";
import * from "files-scs:config/ldp/handler/components/operation-metadata.json";
import * from "files-scs:config/ldp/handler/components/request-parser.json";
import * from "files-scs:config/ldp/handler/components/response-writer.json";

const serverLink = text => link(`urn:solid-server:default:${text}`)

const operationHandler = new AuthorizingHttpHandler({ args: {
      credentialsExtractor: serverLink("CredentialsExtractor"),
        modesExtractor: serverLink("ModesExtractor"),
        permissionReader: serverLink("PermissionReader"),
        authorizer: serverLink("Authorizer"),
        operationHandler: serverLink("OperationHandler")
    }})

export {
  /**
  * The main entry point into the main Solid behaviour.
  */
  "urn:solid-server:default:LdpHandler": new ParsingHttpHandler({args: {
    requestParser: serverLink("RequestParser"),
    metadataCollector: serverLink("OperationMetadataCollector"),
    errorHandler: serverLink("ErrorHandler"),
    responseWriter: serverLink("ResponseWriter"),
    operationHandler,
  }})
}

Rather than having the @context comment at the top it may make sense to have

const link = context("https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^4.0.0/components/context.jsonld")

There are plenty of possible refinements here but just wanted to get my initial ideas down

jeswr avatar May 28 '22 01:05 jeswr

Thanks for the suggestion!

github-actions[bot] avatar May 28 '22 01:05 github-actions[bot]

I'm not convinced yet that we really need a JS-based serialization, but I'm definitely open to convincing :-) (I'd rather focus on making the declarative form more user-friendly)

rubensworks avatar May 30 '22 06:05 rubensworks

I'm not convinced yet that we really need a JS-based serialization

My argument would be that as tooling such as CSS and Comunica become more widespread, there will be people (for instance front-end developers) with a limited understanding of RDF to be able to add certain fixes/features to these tools; so giving something similar to what they are already working with enables them to easily do so.

I'd rather focus on making the declarative form more user-friendly

Indeed this may be a better option - I just don't have an intuition for how to make it easily accessible to the audience of those with limited RDF knowledge.

jeswr avatar May 30 '22 07:05 jeswr

there will be people (for instance front-end developers) with a limited understanding of RDF to be able to add certain fixes/features to these tools; so giving something similar to what they are already working with enables them to easily do so.

That's why we're using JSON(-LD) 🙂 Ideally, end-users should not need to be aware that they are even writing RDF.

And you could stretch that argument even further, and say that there will be people with limited understanding of programming. For those, JSON might be a lower barrier to entry compared to JS.

rubensworks avatar May 30 '22 07:05 rubensworks

Just to throw in my 2 cents:

Whichever solution or changes are being done, I think it's important that there is only 1 "final" configuration serialization. Otherwise it becomes much harder for configurations to be reused/shared if groups use different serialization formats.

I'm not convinced that a TS solution like the one above would help that much (but I could be wrong of course). It still has many of the weird/difficult parts of Components.js where you still need to know what is going on before you can make changes or additions.

I would be more fan of extra tooling to clarify what is going on or potentially convert between different serializations to make them more readable. For example, it is already possible for Components.js to generate a JS file that contains all the instantiations of the classes based on the configurations. Perhaps something could be done with that functionality so it is split over different files similarly to how the config files are made, and also make the output more readable. Although I'm not sure how to handle classes being defined over multiple config files there.

If you want to start from TS I wonder if it might be interesting to have some way to simply have a (mostly?) Components.js unaware initialization file from which Components.js configuration can be made. Might be difficult to solve the imports there though.

My ideal Components.js solution is some sort of tool in which you can load a Components.js configuration that visualizes how everything is connected for you and allows you to make edits that are immediately validated.

joachimvh avatar May 30 '22 07:05 joachimvh

For reference, something like https://github.com/LinkedSoftwareDependencies/Components.js/issues/13 would solve most of the current usability problems I think.

rubensworks avatar May 30 '22 08:05 rubensworks

For reference, something like #13 would solve most of the current usability problems I think.

One issue with that which Jackson also mentions is that it forces people to use a specific IDE (unless multiple plugins get made). I work in WebStorm (IntelliJ), but I know other people working on CSS use VS Code for example. The above issue mentions IntelliJ, but that one isn't even free for TS development.

joachimvh avatar May 30 '22 08:05 joachimvh

but I know other people working on CSS use VS Code for example.

If that's the case my view in regards to an extension would be to implement the extension functionality using the Language Server Protocol so that it works with, but is not tied to VScode.

jeswr avatar May 30 '22 08:05 jeswr

the Language Server Protocol

Oh, that's interesting. Will add that to #13

rubensworks avatar May 30 '22 08:05 rubensworks