LinkedSoftwareDependencies / Components.js

🧩 A semantic dependency injection framework
https://componentsjs.readthedocs.io/
Other
41 stars 6 forks source link

Custom components.js serialization #97

Open jeswr opened 2 years ago

jeswr commented 2 years ago

Issue type:


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

github-actions[bot] commented 2 years ago

Thanks for the suggestion!

rubensworks commented 2 years ago

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)

jeswr commented 2 years ago

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.

rubensworks commented 2 years ago

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.

joachimvh commented 2 years ago

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.

rubensworks commented 2 years ago

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

joachimvh commented 2 years ago

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.

jeswr commented 2 years ago

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.

rubensworks commented 2 years ago

the Language Server Protocol

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