Node.js ORM written in TypeScript for type lovers.

View the Project on GitHub twinlogix/typetta

The Data API

Typetta is the only open-source library that allows you to expose your database via a fully auto-generated GraphQL API.

Unlike other services that have the same goal, being just a small and light package you can use Typetta on your preffered NodeJS stack and with your own infrastructure.

There are several ways a GraphQL API of your data can be useful for your organization:

Having such an auto-generated with just a few lines of code allows you to focus on your business.

Start your GraphQL server less then a minute

Typetta provide ready-to-use typedefs and resolvers that you can easily use to create a GraphQL Endpoint with all the CRUD operations to manage the entities of your data model. The Typetta solution is fully compatible with all GraphQL servers on NodeJS (GraphQL Yoga, Apollo Server, Mercurius, express-graphql).

Following an example using Apollo Server and generated code from the default src/generated directory:

import { ApolloServer } from 'apollo-server'
import { resolvers } from './generated/resolvers'
import { mergeTypeDefs } from '@graphql-tools/merge'
import inputTypeDefs from './generated/operations'
import schemaTypeDefs from './user.typedefs'
import { typeDefs as typettaDirectivesTypeDefs } from '@twinlogix/typetta'
import { EntityManager } from './generated/typetta'

export type Context = { entityManager: EntityManager }

const server = new ApolloServer({
  typeDefs: mergeTypeDefs([
    inputTypeDefs,
    schemaTypeDefs,
    typettaDirectivesTypeDefs,
  ]),
  resolvers,
  context: () => ({ entityManager: new EntityManager() }),
})

server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`)
})

Typedefs and resolvers are pretty standard components of a GraphQL Schema. You can pass them directly to your server and start a GraphQL Endpoint with default CRUD operations, but you can also compose them in a more custom implementation, using partially generated code and overring what you need.

This gives you maximum flexibility in the implementation of your backend. Adding some kind of authentication as a middleware, you will have a ready to use GraphQL back-end with nearly zero custom implementations.

Example of autogenerated endpoint GraphQL

Take this model as example:

type User @entity @memory {
  id: ID! @id(from: "generator")
  name: String!
  posts: [Post!] @foreignRef(refFrom: "userId")
}

type Post @entity @memory {
  id: ID! @id(from: "generator")
  userId: ID!
  content: String!
  metadata: Metadata
}

type Metadata {
  tags: [String!]
  views: Int
}

and this Typetta configuration:

schema: src/schema.ts
outputDir: src/generated
generateGraphQLOperations:
  context: 
    type: '../index#Context'
    path: entityManager

After the Typetta generation, inside the folder src/generated will be present the files needed to setup a working GraphQL endpoint. The endpoint will offer CRUD (insert, update, and read) operations for all the @entity defined in the model. By configuring the security layer you can also setup a secured endpoint.

Here some example of Mutation and Query that can be performed:

The input type of filters, updates, inserts and sorts are very similar to the Typetta API. Some differences are in the filter input type, specifically the filtering by a field inside an embedded are not implemented with the dot notation but with embedded notation. Same thing for the update input type.

$and, $or and $nor operator are renamed to and_, or_ and nor_ because GraphQL does not support $ character.

The has filter operator is present for all fields that are arrays and only match if the array contains one or more elements that match the value. This filter: filter: { metadata: { tags: { has: "fun" } } } match all posts that have the fun tag inside the metadata.

A complete example can be found here.