Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run backend graphql standalone #1

Open
plmercereau opened this issue Nov 24, 2020 · 7 comments
Open

run backend graphql standalone #1

plmercereau opened this issue Nov 24, 2020 · 7 comments

Comments

@plmercereau
Copy link
Contributor

Hello,

First of all congrats for this great work!
Is there a way to run the backend standalone i.e. only the graphql endpoint without the react frontend?
I see the backend directory could do the job, but it seems its code is somehow duplicated in react-app/pages/api, and it would require some minor refactoring for instance to accept Hasura endpoint and admin secret from env vars.

And also ideally: do you plan to build and maintain it in the official Hasura Docker Hub repository?
Thanks in advance!

@GavinRay97
Copy link
Member

Hey, thank you!

Yeah so initially, it was split into two layers. There was just the GraphQL service running from /backend, and then prototype had used client-side only/traditional SPA React.

Then when it came to hosting it for public demo, it was easier to just move the backend component inside of a Next.js app so there was only a single platform to deploy. Next.js uses zero SSR functionality here, I guess we could have served an index.html + bundle.js from an Express API as well.

One approach may be to extract the backend logic out to a separate folder, and then allow you to import it and plug it in however you like.

So this bit could be exported from somewhere:

const resolvers = {
  JSON: GraphQLJSON,
  JSONObject: GraphQLJSONObject,
  Query: {
    metadata: async () => {
      const request = await runMetadataQuery({
        type: "export_metadata",
        args: {},
      })
      return request.json()
    },
    postgres: async () => {
      const data = {
        columns: await sqlQuery({
          query: getColumns,
          metadataClientQuery: runMetadataQuery,
        }),
        tables: await sqlQuery({
          query: getTables,
          metadataClientQuery: runMetadataQuery,
        }),
        // <SNIPPED>
      }
      return postgresMetadataQueryToGQLResult(data)
    },
  },
}

const apolloServer = new ApolloServer({ typeDefs, resolvers })

And then whether in an Express/Fastify/Next.js app, you would just import the apolloServer instance and start serving it/piping requests through it.

Is that roughly what you had in mind?

And also ideally: do you plan to build and maintain it in the official Hasura Docker Hub repository?

I'm not 100% sure about this, will have to check.
If you wanted to build your own, I think this should work:

FROM node:15.2-alpine as BUILD_IMAGE

WORKDIR /app
COPY package.json yarn.lock ./

# Install dependencies
RUN yarn install --frozen-lockfile

COPY . .

# Build
RUN yarn build
# Remove dev dependencies
RUN npm prune --production

FROM node:15.2-alpine

WORKDIR /app

# Copy from build image
COPY --from=BUILD_IMAGE /app/package.json ./package.json
COPY --from=BUILD_IMAGE /app/node_modules ./node_modules
COPY --from=BUILD_IMAGE /app/.next ./.next
COPY --from=BUILD_IMAGE /app/public ./public

EXPOSE 3000
CMD ["yarn", "start"]

@plmercereau
Copy link
Contributor Author

plmercereau commented Nov 24, 2020

Hello @GavinRay97,
Thanks for your quick reply and your detailed explanations!
I was indeed considering poaching the code into an express application, but wanted to avoid this as I would then not benefit from the possible updates that would come out of this official repo... And it would make contributions more difficult as well ;)
Yes, I agree a custom docker image won't be a big deal, but here again, I would need to stay synced with the updates to come :)
FYI I am considering using the dictionary to automatically generate some kind of CRUD components in Vue - I worked on a similar thing as this backend a while back, but it was really scrappy...

@GavinRay97
Copy link
Member

Ah, you're the person behind the Platypus stuff that eventually got merged into Hasura Backend Plus! Really cool work!

I see your point about maintaining updates from upstream in your own project.

So I would imagine that you'd want to use maybe something like a git submodule, where you have the repo for the backend inside of your own projects and you can use that to fetch updates from master?

Will see what I can do about refactoring this a bit over the current week so that it's more modular.

Would love to see anything you make from this with Vue! Huge fan, been writing it since Vue 2 release in 2016, and absolutely in love with the Composition API from Vue 3. If you hit a roadblock integrating this, more than happy to help there if possible 👍

Maybe we could even share it with the community, if you intend to make it public? Would be really awesome =D

@plmercereau
Copy link
Contributor Author

Thanks for your message! Yes we are quite proud of the work done on Hasura Backend Plus v2 :)

I'm not really fond of git submodules, I hope we could find a way to allow splitting the backend from the frontend - maybe in publishing a distinct "api" NPM package.

About using the data dictionary with Vue, I am considering two approaches: either generating the components + composables from the dictionary, or making things a bit more generic in generating JSON schema + other stuff to make it work with RxDB (and then, be able to plug either Vue or React components). As I have an offline-first use case, I may try the RxDB approach.

I am a bit busy for the next two weeks, but of course I will make it public.

In the meantime I prepared a small PR

@plmercereau
Copy link
Contributor Author

plmercereau commented Nov 26, 2020

Another approach would be to create view from the sql requests you defined, to put them in a dedicated Postgres schema in the Hasura server, and to add relationships between them e.g. one-to-many table-columns etc.
The dictionary API could then be accessed through the main Hasura GraphQL endpoint.
We could efine an Hasura server parameter/env var that would activate/deactivate the data dictionary from the HGE server.
In my opinion it would probably be the best option as it would dramatically simplify things in using existing Hasura features with little to no overhead.

I could work on the metadata/migration files that would set such a system, but I would need to know if the Hasura team agrees with such an architecture and will include it to HGE.

@GavinRay97
Copy link
Member

GavinRay97 commented Nov 30, 2020

We could efine an Hasura server parameter/env var that would activate/deactivate the data dictionary from the HGE server.
In my opinion it would probably be the best option as it would dramatically simplify things in using existing Hasura features with little to no overhead.

So, there's already a "hidden" GraphQL API for DB metadata, that Hasura just doesn't expose because the tables/schema in the DB are set to is_system_defined: true.

This whole backend was essentially a temporary patch/workaround for the fact that we don't have a user-facing solution for enabling and using this API, which hopefully will change at some time in the future. You could actually use this API that already exists in Hasura for fetching this information I'm fairly certain, it's just not necessarily "supported".

This auto-generated GraphQL API with all the standard Hasura query operators would be the ideal solution.

From internal conversations, I think the hope was to try to eventually allow this to be toggled and exposed via something like /v1/graphql/metadata or /v1/metadata, which would be optimal because then you don't need to deploy external services.

Not sure how high on the priority list/roadmap this is, but it would be a killer feature for building tooling and things like admin dashboards, CMS-like apps, etc on top of Hasura.

If you want to see what I mean, go to the Run SQL tab, and try the below command, then click Reload metadata:

update hdb_catalog.hdb_table set is_system_defined = false;

image

To restore, run:

update hdb_catalog.hdb_table set is_system_defined = table_schema in ('hdb_catalog', 'information_schema');

@plmercereau
Copy link
Contributor Author

plmercereau commented Dec 1, 2020

Ah! Changing is_system_defined ! Very nice hack!

Not sure how high on the priority list/roadmap this is, but it would be a killer feature for building tooling and things like admin dashboards, CMS-like apps, etc on top of Hasura.

Couldn't agree more.

I am still struggling to understand the Hasura roadmap. Still waiting for key features while they are supposed to be on top of the priority list. I personally don't believe anymore it is worth waiting for a missing feature to be delivered even when the Hasura team set it as p/high. Examples: multiple roles (waiting for it for more than two years), a more granular permissions system here and there (> one year). 😭

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants