1.0.36 • Published 2 years ago

activeql-server v1.0.36

Weekly downloads
96
License
MIT
Repository
github
Last release
2 years ago

ActiveQL Server

This is the server package for ActiveQL - a framework for building domain driven GraphQL APIs with an oppionated approach and convention over configuration and DRY in mind. Based on a simple domain configuration (mainly entities with attributes and their relationships) it

  • generates a full GraphQL schema with aspects like searching, sorting, paging, permission access etc.
  • provides a full fledged GraphQL API with resolvers
  • allows to be extended for any non-convention requirement with custom code
  • provides an Admin UI for basic CRUD applications; see: https://www.npmjs.com/package/activeql-admin-ui

You can find the full documentation and tutorial here.

Installation

To start developing a GraphQL API you could embedd this library in your Express application - but we recommend one the following methods that provides you with an instantly up-and-running environment.

Application Generator

The easiest way to start is the ActiveQL application generator at https://github.com/betterobjects/activeql-generator

You can create a new ActiveQL application in the folder my-activeql (or any other name) with the following command:

npx betterobjects/activeql-generator my-activeql

Starter-Application

If you can't use npx you can also clone the ActiveQL-Starter-Application at https://github.com/betterobjects/activeql-starter

git clone https://github.com/betterobjects/activeql-starter

Install dependencies

Please call npm install in the folder

cd my-activeql/express
npm install

The generated and starter application also include an Angular Admin UI client. If you want to use this Admin UI you also have to call npm install in the folder ./my-activeql/angular.

Start developing

In the folder ./express/activeql/domain-configuration create a YAML file, e.g. car.yml with the following content:

entity:
  Car: 
    attributes: 
      licence: Key
      brand: String!
      mileage: Int

Start the server

cd express
npm run server

This will start a GraphqlAPI endpoint at http://localhost:4000/graphql.

If you point your browser to this address you will find full fledged GraphQL API whith many queries and mutations you can interact with. For reading / storing data an embedded MongoDB-like database NeDB is used per default. You can change the used database of course.

To create a car you could call the mutation:

mutation {
  createCar( car: { licence: "HH AQ 2021" brand: "Mercedes", mileage: 10000 } ){
    car{ id licence brand mileage }
  }
}

with the submition from your GraphQL API

{
  "data": {
    "createCar": {
      "car": {
        "id": "GjgoJZ9RNHPQ1Pij",
        "licence": "HH AQ 2021",
        "brand": "Mercedes",
        "mileage": 10000
      }
    }
  }
}

The whole generated schema from the example above would look like:

type Car {
  id: ID!
  licence: String!
  brand: String!
  color: String
  mileage: Int
  createdAt: DateTime!
  updatedAt: DateTime!
}

input CarCreateInput {
  licence: String!
  brand: String!
  color: String
  mileage: Int
}

input CarFilter {
  id: IDFilter
  licence: StringFilter
  brand: StringFilter
  color: StringFilter
  mileage: IntFilter
}

enum CarSort {
  licence_ASC
  licence_DESC
  brand_ASC
  brand_DESC
  color_ASC
  color_DESC
  mileage_ASC
  mileage_DESC
  id_ASC
  id_DESC
}

input CarUpdateInput {
  id: ID!
  brand: String
  color: String
  mileage: Int
}

scalar Date

scalar DateTime

input EntityPaging {
  page: Int!
  size: Int!
}

type EntityStats {
  count: Int!
  createdFirst: Date
  createdLast: Date
  updatedLast: Date
}

input IDFilter {
  is: ID
  isNot: ID
  isIn: [ID]
  notIn: [ID]
  exist: Boolean
}

input IntFilter {
  is: Int
  isNot: Int
  lowerOrEqual: Int
  lower: Int
  greaterOrEqual: Int
  greater: Int
  isIn: [Int]
  notIn: [Int]
  between: [Int]
}

scalar JSON

type Mutation {
  ping(some: String): String
  login(username: String!, password: String!): String
  createCar(car: CarCreateInput): SaveCarMutationResult
  updateCar(car: CarUpdateInput): SaveCarMutationResult
  deleteCar(id: ID): [String]
  createUser(user: UserCreateInput): SaveUserMutationResult
  updateUser(user: UserUpdateInput): SaveUserMutationResult
  deleteUser(id: ID): [String]
  seed(truncate: Boolean): [String]
}

type Query {
  ping: String
  jwtValid: Boolean
  car(id: ID!): Car
  cars(filter: CarFilter, sort: CarSort, paging: EntityPaging): [Car]
  carsStats(filter: CarFilter): EntityStats
  user(id: ID!): User
  users(filter: UserFilter, sort: UserSort, paging: EntityPaging): [User]
  usersStats(filter: UserFilter): EntityStats
  domainConfiguration(seeds: Boolean, customQueriesMutationsSrc: Boolean): JSON
}

type SaveCarMutationResult {
  validationViolations: [ValidationViolation]!
  car: Car
}

type SaveUserMutationResult {
  validationViolations: [ValidationViolation]!
  user: User
}

input StringFilter {
  is: String
  isNot: String
  in: [String]
  notIn: [String]
  contains: String
  doesNotContain: String
  beginsWith: String
  endsWith: String
  caseSensitive: Boolean
  regex: String
}

type User {
  id: ID!
  username: String!
  roles: [String!]
  createdAt: DateTime!
  updatedAt: DateTime!
}

input UserCreateInput {
  username: String!
  roles: [String!]
  password: String!
}

input UserFilter {
  id: IDFilter
  username: StringFilter
}

enum UserSort {
  username_ASC
  username_DESC
  roles_ASC
  roles_DESC
  password_ASC
  password_DESC
  id_ASC
  id_DESC
}

input UserUpdateInput {
  id: ID!
  roles: [String!]
  password: String!
}

type ValidationViolation {
  attribute: String
  message: String!
}