active-mdx icon indicating copy to clipboard operation
active-mdx copied to clipboard

GraphQL Server

Open rawkode opened this issue 3 years ago • 4 comments

Would it be possible to expose this as a read-only GraphQL server?

I love the idea of keeping all my data in Git, but I'd still like to consume it from other services

rawkode avatar Feb 11 '22 12:02 rawkode

Yes it absolutely would. It is something I've been meaning to get around to. I'll give you a brain dump of my current thoughts on it in case you want to try it out.

Here is an example of a plugin Google Sheets Plugin

I would develop this as a plugin

import { Collection } from '@active-mdx/core'
import GraphQlPlugin from '@active-mdx/graphql'

export const collection =  new Collection({
  rootPath: "./docs"
}).use(GraphQlPlugin, { ...options })

That plugin would define a function on the collection to generate a graphql API.

I think you could generate the entire graphql API without needing custom code, unless you wanted to.

Here is an ActiveMDX project https://github.com/soederpop/active-mdx/tree/main/packages/software-project-demo-site/docs

If you import this module, you are getting an instance of the ActiveMDX Collection

The collection exposes information about the available model classes

import docs from "./docs/index.mjs"

docs.modelClasses // => [Epic, Story, Standup, Decision]

Each model class has a static property inflections, in this example I can go from the Epic and Story model to "epics", "stories". These names could be used to generate query functions.

Each model class also has an availableQueries property, for pre-determined queries you define on your model class. These could be used to generate available graphql queries as well.

Each model class can also, optionally export a joi schema ( for validation purposes. ) I think this can be inspected somehow to generate a graphql type for each of the models.

So I think using this data, you could generate a graphql schema, as well as resolver functions.

// resolvers.js
module.exports = {
  Query: {
    epics: (_, __, { collection }) =>
      collection.query('Epic').fetchAll()
  }
};

I would have every node / object have common properties like id, model type, meta, title, ast. etc.

Finally, you would just need to wrap it with like apollo-graphql, but in the end you would just be able to say

collection.createGraphqlApi(options)

and get something you could serve with express or whatever.

soederpop avatar Feb 24 '22 06:02 soederpop

You can call describe() on a joi schema.

{
  "type": "object",
  "flags": {
    "unknown": true
  },
  "keys": {
    "meta": {
      "type": "object",
      "flags": {
        "presence": "required",
        "unknown": true
      },
      "keys": {
        "status": {
          "type": "string",
          "flags": {
            "presence": "required"
          },
          "rules": [
            {
              "name": "pattern",
              "args": {
                "regex": "/^(created|in-progress|qa|approved|complete)$/",
                "options": {
                  "name": "valid statuses"
                }
              }
            }
          ]
        },
        "estimates": {
          "type": "object",
          "flags": {
            "unknown": true,
            "presence": "required"
          },
          "keys": {
            "high": {
              "type": "number",
              "flags": {
                "presence": "required"
              }
            },
            "low": {
              "type": "number",
              "flags": {
                "presence": "required"
              }
            }
          }
        },
        "github": {
          "type": "object",
          "keys": {
            "issue": {
              "type": "number"
            }
          }
        }
      }
    }
  }
}

You could easily take that object and generate a graphql type.

soederpop avatar Feb 24 '22 07:02 soederpop

@rawkode just pushed up a commit. still need to document and test.

Screen Shot 2022-02-24 at 3 25 14 AM

If you clone the repo and run yarn

then

$ cd packages/software-project-demo-site
$ node scripts/graphql.mjs

It will start a graphql server you can open on http://localhost:4000

Just a proof of concept of what is possible.

To use it you need @active-mdx/core and @active-mdx/graphql >= 0.9.1

soederpop avatar Feb 24 '22 08:02 soederpop

wow

bketelsen avatar Mar 02 '22 18:03 bketelsen