Giter Club home page Giter Club logo

axolotl's Introduction

Vector 902 (Stroke) (1)

From the GraphQL Editor and Aexol Studio teams, comes a Framework ensuring GraphQL Resolvers and arguments type-safety. Written in TypeScript.


Tip

Check our full documentation and the Discord channel:
Full documentation
Discord channel


😮 Features

Axolotl is a framework overlord/wrapper thats lets you forget about type-casting and looking into schemas. When there is no drama, only efficiency remains.


  • ⚙️ Generates models at runtime during development - which ensures type safety
  • 🏃 Enables seamless migration between different GraphQL Servers like GraphQL Yoga and Apollo Server
  • 🤓 Lets you write your own adapters for various purposes
  • 🐙 Supports micro-federation! It allows to merge different schemas and resolvers inside one repository.
  • 🦕 Supports Deno from version 0.2.7. It works with Deno in production.
  • 😂 Is very easy to setup, start and integrate. You just need to npx @aexol/axololtl create-yoga
  • 🦎 includes modularium, a package with installable GraphQL schemas with backend

🤔 The Origin Story

Writing GraphQL for backend developers remains a complicated process when you want to take the schema-first approach instead of going code-first. I was in the type-safety rabbit hole while building GraphQL Zeus (a GraphQL client with almost 1 million downloads). Maintaining Zeus and developing with the constantly-changing TypeScript proved to be really hard.
Over the years, I have come to understand that there was even more to it: we needed an evolutionary framework. I decided to write something simpler. Something that the community needed that integrated everything using the same knowledge. Something, ultimately, much more powerful.

This is how Axolotl was born.


😇 How It Works

Axolotl provides type-safety and lets you choose the adapter (or write your own). It allows you to develop your GraphQL project quickly and efficiently. How it runs it also depends on the underlying framework you choose.


Repository

Element Description
Adapters To develop adapters for popular nodejs frameworks
Examples To experiment with axolotl and its packages
Modularium Installable code chunks for your project

Micro-federation
To use the micro-federation feature in axolotl

- Micro-federation means that all the modules are located within one project or one monorepo or are distributed as npm packages
- The axolotl projects are merged to the supergraph later

Development

Important

To start developing you need to know a few things.


This is an npm workspaces monorepo.


There is a sequential build order for commands as seen below:

 npm run build --ws --if-present

To run an example execute you need to type in:

 npm run start -w beerpub

axolotl's People

Contributors

aexol avatar aleksanderbondar avatar taksebiegam avatar dtomart avatar magdapuch avatar

Stargazers

dinwwwh avatar Tim Kersey avatar Can Evgin avatar Hakim Saoudi avatar Sakesun avatar Eduardo Borges avatar Leonid Pyrlia avatar  avatar Adam Grabowski avatar  avatar  avatar  avatar  avatar Marcin Falkowski avatar Damian Konarowski avatar Michał C avatar Tomek Poniatowicz avatar PavelBrui avatar Anna Łysiuk avatar mic avatar  avatar Artur avatar Adrianna Gregorczuk avatar  avatar Pawel avatar Tomasz Gajda avatar  avatar

Watchers

 avatar  avatar

axolotl's Issues

Create a federation add command

npx @aexol-studio/axolotl federation add shop

This command will add separate folder with all the axolotl files and it will add the folder to the federation config

Create a federated config

This config will contain basic info like normal config and additional info for federated schemas:

{
    "schema": "schema.graphql",
    "models": "src/models.ts",
    "axolotl": "src/axolotl.ts",
    "federation":[
        {
            "schema":"src/beers/schema.graphql",
            "models": "src/beers/models.ts",
            "axolotl": "src/beers/axolotl.ts"
        },
        {
            "schema":"src/shop/schema.graphql",
            "models": "src/shop/models.ts",
            "axolotl": "src/beers/axolotl.ts"
        }
    ]
}

From each config from federation - models generate in those folders

Sort inspect methods into group

First Group should contain fields that are of type type. Second group fields of custom scalar type. Third group for enums and plain scalars.

Provide a method to scaffold a file with the following content

import { createResolvers } from '@/src/axolotl.js';

export default createResolvers({
  // put your resolvers here
});

Command:

axolotl resolver [resolver_path]

Then it asks for the root type UserOps in our case and then for the file path

Example

axolotl resolver src/UserQuery.ts

Provide error on invalid key in axolotl resolvers

const resolvers = createResolvers({
  Query: {
    admin: mustBeUser,
    login,
    houses: async () => {
      return MongOrb('House').collection.find({}).toArray();
    },
    housePublic: async (input, args) => {
      return MongOrb('House').collection.findOne({ _id: args.id });
    },
   invalidField: async() => {
     // this should throw
   }
  }});

Create axolotl.ts generation

Create axolotl file generation will all the needed exports when the file is not present.

import { Directives, Models } from '@/src/models.js';
import { Axolotl } from '@aexol/axolotl-core';

export const { applyMiddleware, createResolvers, createDirectives, adapter } = Axolotl(YOUR_ADAPTER)<
  Models,
  Directives
>();

Provide validate types only response function

Sometimes it would we useful to validate response type. The function should also give a way to transform the validated type:

import { getUserOrThrow } from '@/src/auth.js';
import { createResolvers } from '@/src/axolotl.js';
import { GraphQLError } from 'graphql';

export const Mutation = createResolvers({
  Mutation: {
    public:() => {
      return {}
    },
    user:async ([,,context],args,validate) => {
      const authHeader = context.request.headers.get("Authorization")
      if(!authHeader) throw new GraphQLError("You must be logged in to use this resolver")
      return validate(getUserOrThrow(authHeader))
    }
  },
})

This should be identity function only used for type check without real validation of response only to help developer experience

const validate = <Z={}>(o:T extends OUR_RESPONSE_TYPE):T => o

Overloading would look like that

import { getUserOrThrow } from '@/src/auth.js';
import { createResolvers } from '@/src/axolotl.js';
import { GraphQLError } from 'graphql';

export const Mutation = createResolvers({
  Mutation: {
    public:() => {
      return {}
    },
    user:async ([,,context],args,validate) => {
      const authHeader = context.request.headers.get("Authorization")
      if(!authHeader) throw new GraphQLError("You must be logged in to use this resolver")
      return validate<ReturnType<typeof validate> & { smth:string }>(getUserOrThrow(authHeader))
    }
  },
})

[Readme] Better code snippets

remove $ from shell command snippets to improve user ex.

$ npm i @aexol/axolotl-core @aexol/axolotl-stucco

This code causes an error in Windows when copying because it has a $ sign inside

fix:

npm i @aexol/axolotl-core @aexol/axolotl-stucco

Provide function to transfer source type from one's resolver response to another resolver source inject

import { MongOrb, QuestionModel } from '@/src/orm.js';
import { createResolvers } from '@/src/axolotl.js';

export const Question = createResolvers({
  Question:{
    user: async ([source]) => {
      const questionSource = source as QuestionModel
      return MongOrb("User").collection.findOne({
        username: questionSource.user
      })
    }
  },
});

Normally we just import the type from some ORM and cast the type of source. But we can do better.

import { MongOrb, QuestionModel } from '@/src/orm.js';
import { createResolvers, fromSource } from '@/src/axolotl.js';
import { Query } from '@/src/axolotl.js';

export const Question = createResolvers({
  Question: fromSource(Query.questionById)({
    user: async ([source]) => {
      return MongOrb("User").collection.findOne({
// source is already typed
        username: source.user
      })
    }
  }),
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.