Pylon Documentation

repository·main·Indexed 18 days ago

https://github.com/getcronit/pylon

A framework for building GraphQL APIs that automatically generates schemas from TypeScript service logic. Pylon eliminates manual SDL maintenance by inferring schemas from TypeScript type annotations, interfaces, and unions. It supports multiple runtimes including Bun, Node.js, Cloudflare Workers, and Deno, and features integrated support for ZITADEL authentication, Sentry monitoring, and automatic type resolution for polymorphic fields.

Tokens
32.8K
Snippets
120
Records
152
Agent score
63%

What's inside Pylon

  1. Key features of Pylon 1.0

    main

    Pylon 1.0 provides several built-in capabilities for GraphQL development:

    • Automated Schema Generation: Generates schemas directly from TypeScript code.
    • Authentication and Authorization: Integrated support for ZITADEL for user management and access control.
    • Logging and Monitoring: Real-time error monitoring and alerting via Sentry.
    • Context Management: Ability to implement custom logic based on incoming requests.
    • Developer Tools: Includes a built-in GraphQL Playground and Viewer for API interaction and schema visualization.
  2. What is Pylon?

    main
    Pylon is a tool that automates the creation of GraphQL schemas by leveraging TypeScript type annotations. Instead of manually writing and maintaining schema definition files, Pylon scans your TypeScript functions and automatically generates a corresponding GraphQL schema. This ensures that your GraphQL schema remains in sync with your application code, providing enhanced type safety and reducing manual errors.
  3. How interfaces work in Pylon

    main

    In Pylon, TypeScript interface definitions are automatically translated into GraphQL interfaces. This allows you to define common fields that multiple types must implement, ensuring consistency across your schema.

    When a TypeScript interface is extended by other interfaces, Pylon generates the corresponding implements relationship in the GraphQL schema.

    Example

    import {app, ID} from '@getcronit/pylon'
    
    interface Node {
      id: ID
    }
    
    interface User extends Node {
      name: string
    }
    
    interface Post extends Node {
      title: string
    }
    
    export const graphql = {
      Query: {
        user: (id: ID): User => {
          // Implementation
        },
        post: (id: ID): Post => {
          // Implementation
        },
        node: (id: ID): Node => {
          // Implementation
        }
      }
    }
  4. How Pylon works: Automatic GraphQL schema generation

    main

    Pylon is a framework for building GraphQL APIs where the schema is automatically inferred from your TypeScript service logic. Instead of writing manual GraphQL SDL (Schema Definition Language), you define your Query and Mutation objects using TypeScript. Pylon uses these definitions to generate the corresponding GraphQL schema, ensuring that your API and your service logic are always in sync and type-safe.

    import {app} from '@getcronit/pylon'
    
    export const graphql = {
      Query: {
        user: (id: string) => {
          return {
            id,
            name: 'John Doe',
            email: 'johndoe@example.com'
          }
        }
      },
      Mutation: {
        updateUserEmail: (id: string, newEmail: string) => {
          return {
            id,
            email: newEmail
          }
        }
      }
    }
    
    export default app
  5. Use Bindings for sensitive configuration

    main

    Bindings are used to store sensitive information like API keys or database URLs. They are accessed via ctx.env within the request context. To use them with full type safety, you must declare them in the Bindings interface within your pylon.d.ts file. At runtime, these values are typically provided via environment variables (e.g., in a .env file).

    // pylon.d.ts
    import '@getcronit/pylon'
    
    declare module '@getcronit/pylon' {
      interface Bindings {
        SECRET: string
      }
    
      interface Variables {}
    }
    // src/index.ts
    import {app, getContext} from '@getcronit/pylon'
    
    export const graphql = {
      hello: () => {
        const ctx = getContext()
        const secret = ctx.env.SECRET
        // ... use secret
      }
    }
  6. How unions work in Pylon

    main

    TypeScript union types (e.g., type A = B | C) are automatically translated into GraphQL union types. This is useful for representing heterogeneous collections or results that could be one of several distinct types.

    Example

    type SearchResult = User | Post
    
    export const graphql = {
      Query: {
        search: (query: string): SearchResult[] => {
          // Implementation to search users and posts
        }
      }
    }
  7. Automatic interface creation from shared union properties

    main

    When you define a TypeScript union type where the member types share common properties, Pylon automatically creates a GraphQL interface containing those shared properties. This optimizes the schema for querying common fields.

    Example

    type Bar = {
      id: ID
      title: string
    }
    
    type Foo = {
      id: ID
      name: string
    }
    
    type Example = Foo | Bar

    This results in a GraphQL schema where Foo and Bar both implement an Example interface containing the id field.

  8. How Pylon and GQty work together

    main

    The integration between Pylon and GQty creates a synchronized full-stack type-safe environment:

    • Server-side: Pylon generates a GraphQL schema automatically from your TypeScript definitions.
    • Client-side: GQty automatically detects and picks up data requirements within your application.

    This synergy provides several key benefits:

    • Automatic data requirements: You no longer need to manually maintain GraphQL queries.
    • Real-time API updates: Breaking changes in your server-side API are instantly reflected in the frontend.
    • Instant type-errors: Breaking changes trigger immediate TypeScript errors in the frontend code exactly where the breakage occurs.
    • Type safety: You get first-class TypeScript support with API documentation available via autocomplete.
  9. Use Variables for request-scoped data

    main

    Variables allow you to store data inside the request context that is accessible throughout the entire request lifecycle. You can set a variable using ctx.set(key, value) (typically in middleware) and retrieve it using ctx.get(key). To enable type safety, declare the variables in the Variables interface in pylon.d.ts.

    // pylon.d.ts
    import '@getcronit/pylon'
    
    declare module '@getcronit/pylon' {
      interface Bindings {}
    
      interface Variables {
        user?: string
      }
    }
    // src/index.ts
    import {app, getContext} from '@getcronit/pylon'
    
    export const graphql = {
      hello: () => {
        const ctx = getContext()
        const user = ctx.get('user') // Typed based on pylon.d.ts
        return user ? `Hello ${user}` : 'Hello Stranger'
      }
    }
    
    app.use(async (ctx, next) => {
      ctx.set('user', 'John Doe')
      await next()
    })
  10. How Pylon handles TypeScript Unions

    main

    Pylon automatically translates TypeScript unions into either GraphQL interfaces or GraphQL unions based on the properties shared between the types:

    1. GraphQL Interface: If the types in the union share common properties, Pylon generates a GraphQL interface containing those shared fields, and the constituent types implement that interface.
    2. GraphQL Union: If the types in the union have no shared properties, Pylon generates a standard GraphQL union.

    This allows you to define complex type hierarchies in TypeScript and have them correctly mapped to your GraphQL schema without manual configuration.

    // Example: Shared properties result in a GraphQL Interface
    type Bar = {
      id: ID
      title: string
    }
    
    type Foo = {
      id: ID
      name: string
    }
    
    type Example = Foo | Bar
    
    // Resulting GraphQL:
    // interface Example { id: ID! }
    // type Foo implements Example { id: ID!, name: String! }
    // type Bar implements Example { id: ID!, title: String! }
  11. How Pylon handles TypeScript Interfaces

    main

    Pylon provides full support for TypeScript interfaces. When you define a TypeScript interface and have classes implement it, Pylon automatically generates the corresponding GraphQL interface. This ensures your GraphQL schema mirrors your TypeScript type hierarchy, promoting code reusability and type safety.

    interface NodeInterface {
      id: string
    }
    
    class NodeC1lass implements NodeInterface {
      constructor(public id: string) {}
    }
    
    class NodeC2lass implements NodeInterface {
      constructor(public id: string) {}
      public extra = 'extra'
    }